home *** CD-ROM | disk | FTP | other *** search
/ Giga Games 1 / Giga Games.iso / net / go / prog / igc070.sh < prev    next >
Encoding:
Linux/UNIX/POSIX Shell Script  |  1993-06-20  |  90.8 KB  |  4,399 lines

  1. #! /bin/sh
  2. # This is a shell archive, meaning:
  3. # 1. Remove everything above the #! /bin/sh line.
  4. # 2. Save the resulting text in a file.
  5. # 3. Execute the file with /bin/sh (not csh) to create:
  6. #    README
  7. #    socket.c
  8. #    igc.c
  9. #    parse.c
  10. #    ascii.c
  11. #    board.c
  12. #    numbers.h
  13. #    igc.h
  14. #    Makefile
  15. #    igc.6
  16. #    BUGS
  17. # This archive created: Mon Jun  7 19:44:51 1993
  18. export PATH; PATH=/bin:/usr/bin:$PATH
  19. if test -f 'README'
  20. then
  21.     echo shar: "will not over-write existing file 'README'"
  22. else
  23. cat << \SHAR_EOF > 'README'
  24.         IGS - Ascii Client by Adrian Mariano
  25.                 adrian@u.washington.edu
  26.                            adrian on igs
  27.  
  28.  
  29. This is an ascii client program for the Internet Go Server.
  30.  
  31. Its purpose is to provide a useable interface to the server with
  32. ASCII character drawn Go boards.
  33.  
  34. This program requires UNIX with sockets capability. 
  35.  
  36. Read the Makefile for instructions on compiling.
  37.  
  38. SHAR_EOF
  39. fi
  40. if test -f 'socket.c'
  41. then
  42.     echo shar: "will not over-write existing file 'socket.c'"
  43. else
  44. cat << \SHAR_EOF > 'socket.c'
  45. #include <sys/types.h>
  46. #include <sys/time.h>
  47. #include <sys/socket.h>
  48. #include <netdb.h>
  49.  
  50. #ifndef WINS            /* Usually want this... */
  51. #include <netinet/in.h>
  52. #else                /* ... but need these for WINS. */
  53. #include <sys/in.h>
  54. #include <sys/inet.h>
  55. #endif
  56.  
  57. #include <fcntl.h>
  58. #include <sys/errno.h>
  59. #include <stdio.h>
  60. #ifndef FD_ZERO
  61. #include <sys/select.h>
  62. #endif
  63. #include "igc.h"
  64.  
  65. /* For some odd systems, which don't put this in errno.h. */
  66.  
  67. extern int errno;
  68.  
  69. char servename[80];
  70. int serveport;
  71. int sock;
  72. char inbuf[1000];
  73. int inptr = 0;
  74. int doecho = 1;
  75.  
  76.  
  77. sethost(s)
  78. char *s;
  79. {
  80.    strcpy(servename, s);
  81. }
  82.  
  83.  
  84. setport(s)
  85. int s;
  86. {
  87.    serveport = s;
  88.  
  89. }
  90.  
  91. void close_connection()
  92. {
  93.    close(sock);
  94. }
  95.  
  96.  
  97. #ifdef DEBUG
  98. FILE *blah;
  99. #endif
  100.  
  101.  
  102. setecho(ec)
  103. int ec;
  104. {
  105.    doecho = ec;
  106. }
  107.  
  108.  
  109. int open_connection()
  110. {
  111.    struct sockaddr_in server;
  112.    struct hostent *hp;
  113.    int ipn;
  114.  
  115.    printf("Opening connection to %s %d\n", servename, serveport);
  116. #ifdef DEBUG
  117.    {
  118.       int d;
  119.       char n[444];
  120.       d = 0;
  121.       do {
  122.      sprintf(n, "dump%d.igc", d);
  123.      blah = fopen(n, "r");
  124.      if (!blah) {
  125.         blah = fopen(n, "w");
  126.         if (blah)
  127.            printf("Creating dump file %s\n", n);
  128.         break;
  129.      }
  130.      close(blah);
  131.      d++;
  132.      if (d > 9) {
  133.         printf("Too many dump files.  Delete dump files (dump?.igc)? ");
  134.         fgets(n, 443, stdin);
  135.         if (n[0] != 'Y' && n[0] != 'y')
  136.            exit(1);
  137.         for (d = 0; d < 10; d++) {
  138.            sprintf(n, "dump%d.igc", d);
  139.            unlink(n);
  140.         }
  141.         blah = fopen("dump0.igc", "w");
  142.         if (!blah) {
  143.            printf("File open error.  Cannot create dump file\n");
  144.            exit(1);
  145.         }
  146.         break;
  147.      }
  148.       } while (1);
  149.       if (!blah) {
  150.      printf("File open error.  Cannot create dump file.\n");
  151.      exit(1);
  152.       }
  153.    }
  154. #endif
  155.    if (sscanf(servename, "%d.%d.%d.%d", &ipn, &ipn, &ipn, &ipn) == 4)
  156.       server.sin_addr.s_addr = inet_addr(servename);
  157.    else {
  158.       hp = gethostbyname(servename);
  159.       if (hp == 0) {
  160.      puts("Unknown host");
  161.      return -1;
  162.       }
  163.       bcopy(hp->h_addr, &server.sin_addr, hp->h_length);
  164.    }
  165.    server.sin_family = AF_INET;
  166.    server.sin_port = htons(serveport);
  167.    sock = socket(AF_INET, SOCK_STREAM, 0);
  168.    if (sock < 0) {
  169.       perror("socket");
  170.       return -1;
  171.    }
  172.    if (connect(sock, (struct sockaddr *) & server,
  173.            sizeof(struct sockaddr_in)) < 0) {
  174.       perror("connect");
  175.       return -1;
  176.    }
  177.    return 0;
  178. }
  179.  
  180.  
  181.  
  182. sendstr(buf)
  183. char *buf;
  184. {
  185.  
  186. #ifdef DEBUG
  187.    if (doecho && strlen(buf) && blah && buf[0] != '\377')
  188.       fprintf(blah, ">%s<\n", buf);
  189. #endif
  190.    write(sock, buf, strlen(buf));
  191. }
  192.  
  193.  
  194. /* returns 1 if telnet processing ate the character. */
  195.  
  196. #define IAC '\377'
  197. #define DONT '\376'
  198. #define DO '\375'
  199. #define WONT '\374'
  200. #define WILL '\373'
  201. #define AYT '\366'
  202. #define TELOPT_SGA  '\3'
  203. #define TELOPT_ECHO '\1'
  204.  
  205. int dotelnet(ch)
  206. char ch;
  207. {
  208.    static int telcount = 0;
  209.    static char telchars[4];
  210.  
  211.    if (ch == IAC || telcount == 1) {
  212.       telchars[telcount] = ch;
  213.       telcount++;
  214.       if (telcount == 2 && telchars[1] == AYT) {
  215.      telcount = 0;
  216.      sendstr("igc-yes\n");
  217.      return 0;
  218.       }
  219.       return 1;
  220.    }
  221.    if (telcount == 2) {
  222.       telcount = 0;
  223.       telchars[2] = ch;
  224.       telchars[3] = 0;
  225.       if (telchars[2] == TELOPT_ECHO) {
  226.      setecho(telchars[1] == WONT);
  227.      return 1;
  228.       }
  229.       if (telchars[1] == WILL) {
  230.      if (telchars[2] == TELOPT_SGA)
  231.         telchars[1] = DO;
  232.      else
  233.         telchars[1] = DONT;
  234.       } else if (telchars[1] == DO) {
  235.      if (telchars[2] == TELOPT_SGA)
  236.         telchars[1] = WILL;
  237.      else
  238.         telchars[1] = WONT;
  239.       }
  240.       sendstr(telchars);
  241.       return 1;
  242.    }
  243.    return 0;
  244. }
  245.  
  246.  
  247.  
  248.  
  249. int handlechar(retbuf, in)
  250. char *retbuf;
  251. char in;
  252. {
  253.    if (in == '\r')
  254.       return 0;
  255. #ifdef DEBUG
  256.    fputc(in, blah);
  257. #endif
  258.    if (dotelnet(in))
  259.       return 0;
  260.    if (in == '\n') {
  261.       inbuf[inptr] = 0;
  262.       strcpy(retbuf, inbuf);
  263.       inptr = 0;
  264.       return 1;
  265.    } else {
  266.       inbuf[inptr++] = in;
  267.       if (doneline(inbuf, inptr)) {
  268.      inbuf[inptr] = 0;
  269.      strcpy(retbuf, inbuf);
  270.      inptr = 0;
  271.      return 1;
  272.       }
  273.    }
  274.    return 0;
  275. }
  276.  
  277.  
  278.  
  279. int bufdata = 0, bufptr = 0;
  280. char thebuf[1000];
  281.  
  282. int pollserver(retbuf, checkstdin)
  283. char *retbuf;
  284. int checkstdin;
  285. {
  286.    int sel;
  287.    fd_set readers;
  288.  
  289.    FD_ZERO(&readers);
  290.    while (1) {
  291.       while (bufdata) {
  292.      bufdata--;
  293.      if (handlechar(retbuf, thebuf[bufptr++]))
  294.         return 1;
  295.       }
  296.       bufptr = 0;
  297.       if (checkstdin)
  298.      FD_SET(0, &readers);    /* Check stdin */
  299.       FD_SET(sock, &readers);
  300.       sel = select(sock + 1, &readers, NULL, NULL, (struct timeval *) 0);
  301.       if (sel == -1) {
  302.      if (errno != EINTR) {    /* ^Z will do this */
  303.         perror("select");
  304.         return -1;
  305.      }
  306.      continue;
  307.       }
  308.       if (FD_ISSET(sock, &readers)) {
  309.      bufdata = read(sock, thebuf, 1000);
  310.      if (!bufdata)
  311.         return -1;
  312.      if (bufdata < 0) {
  313.         perror("read");
  314.         return -2;
  315.      }
  316.       } else if (FD_ISSET(0, &readers))
  317.      return KEY;
  318.    }
  319. }
  320. SHAR_EOF
  321. fi
  322. if test -f 'igc.c'
  323. then
  324.     echo shar: "will not over-write existing file 'igc.c'"
  325. else
  326. cat << \SHAR_EOF > 'igc.c'
  327. #include "igc.h"
  328. #include <stdio.h>
  329. #include <string.h>
  330. #include <signal.h>
  331. #include <pwd.h>
  332. #include "numbers.h"
  333.  
  334.  
  335. #define RCNAME "/.igcrc"
  336.  
  337.  
  338. #define ATRC 1
  339. #define NOTATRC 2
  340. #define BOTH (ATRC | NOTATRC)
  341.  
  342. char login[20] = "";
  343. char password[20] = "";
  344.  
  345. char friend[MAXFRIENDS][MAXNAME];    /* friends list */
  346. int nfriends = 0;
  347.  
  348. message mesg;            /* structure for getting parsed info from
  349.                  * server */
  350.  
  351. char prefix[21];        /* Text prefix for each outgoing line */
  352. int xcur = -1, ycur = -1;    /* Cursor locations on board */
  353. int boardon = 0;        /* Is the board being displayed? */
  354. int boardmode = 0;        /* Are we on the board? */
  355. int beepcount = 1;        /* Number of beeps to send */
  356. int saybeep = 0;        /* Beep on say strings? */
  357. int tellbeep = 0;        /* Beep on tell strings? */
  358. int friendfilter = 0;        /* Filter login messages for friends? */
  359. int displayintro = 1;           /* Display intro before log in */
  360.  
  361. int ingame = -1;        /* Game which is displayed, -1 for none */
  362. int observing = 0;        /* Are we observing a game? */
  363. int justpeeked = 0;        /* Fixup flag for game number after peek */
  364. int needrestore = 0;        /* Need to restore board? (After status) */
  365. int bschange = 0;        /* boardsize changed?  Used with needrestore */
  366. extern int boardsize;
  367.  
  368. char local[1000], *loc;        /* Buffer for characters typed by local user */
  369.  
  370. struct {
  371.    char white[21], wrank[10], black[21], brank[10];
  372.    int hcap;
  373.    float komi;
  374.    int bbyo, wbyo, wtime, btime;
  375. }  curgame;            /* Information about current game */
  376.  
  377.  
  378. int (*whosort) ();
  379. int (*gamessort) ();
  380.  
  381. #define MAXSITES 10
  382.  
  383. struct {
  384.    char name[50];
  385.    char site[100];
  386.    int port;
  387. }  sitetable[MAXSITES] =
  388. {
  389.    { "hellspark", "hellspark.wharton.upenn.edu", 6969 },
  390.    { "pasteur", "ftp.pasteur.fr", 6969 },
  391.    { "", "", 6969 },
  392.    { "", "", 6969 },
  393.    { "", "", 6969 },
  394.    { "", "", 6969 },
  395.    { "", "", 6969 },
  396.    { "", "", 6969 },
  397.    { "", "", 6969 },
  398.    { "", "", 6969 }
  399. };
  400.  
  401.  
  402. void myexit(ex)
  403. int ex;
  404. {
  405.    if (boardon)
  406.       endAscii();
  407.    exit(ex);
  408. }
  409.  
  410.  
  411. void handleterm()
  412. {
  413.    close_connection();
  414.    myexit(0);
  415. }
  416.  
  417.  
  418. char *getpassword(repeat)
  419. int repeat;
  420. {  
  421. char trash[20];
  422.    if (repeat || !strlen(password)) {
  423.       printf("Password: ");
  424.       for (;;) {
  425.      fgets(password,20,stdin);
  426.      if (feof(stdin)) handleterm();
  427.          if (password[strlen(password)-1]!='\n'){
  428.    password[strlen(password)-1]='\n';
  429.            do{ 
  430.          fgets(trash,20,stdin);
  431.        }while (trash[strlen(trash)-1]!='\n');
  432.  }
  433.      if (strstr(password, "helpigc"))
  434.         printf("You are entering your password for the Internet Go Server.  You will be\nprompted twice for your password if you are creating a new account.  Enter\nthe same password twice in this case.\nPassword: ");
  435.      else if (!strlen(password))
  436.         printf("Empty password not allowed.\nPassword: ");
  437.      else
  438.         break;
  439.       }
  440.    }
  441.    return password;
  442. }
  443.  
  444.  
  445. char *getloginname(repeat)
  446. int repeat;
  447.    char trash[20];
  448.    if (repeat == 1)
  449.       printf("Login failed.\n");
  450.    if (repeat || !strlen(login)) {
  451.       printf("Login: ");
  452.       for (;;) {
  453.      fgets(login,20,stdin);
  454.      if (feof(stdin)) handleterm();
  455.          if (login[strlen(login)-1]!='\n'){
  456.            login[strlen(login)-1]='\n';
  457.            do{
  458.          fgets(trash,20,stdin);
  459.        }while (trash[strlen(trash)-1]!='\n');
  460.      }
  461.      if (strstr(login, "helpigc"))
  462.         printf("You are logging into the Internet Go server.  Type a login name now.\nLogin: ");
  463.      else if (!strlen(login))
  464.         printf("Blank names not allowed.\nLogin: ");
  465.      else
  466.         break;
  467.       }
  468.    } else
  469.       printf("Logging on as %s", login);
  470.    return login;
  471. }
  472.  
  473.  
  474.  
  475. putstr(s)
  476. char *s;
  477. {
  478.    if (boardon) {
  479.       addstring(s);
  480.       addchar('\n');
  481.    } else
  482.       puts(s);
  483. }
  484.  
  485.  
  486. dobeep()
  487. {
  488.    char ch;
  489.    for (ch = beepcount; ch--;)
  490.       putchar(7);
  491. }
  492.  
  493.  
  494. readrc()
  495. {
  496.    struct passwd *pw;
  497.    char rcfilename[1000];
  498.    FILE *rcfile;
  499.    char *var, *val, line[100], saveline[100];
  500.  
  501.    pw = getpwuid(geteuid());
  502.    strcpy(rcfilename, pw->pw_dir);
  503.    strcat(rcfilename, RCNAME);
  504.    if (rcfile = fopen(rcfilename, "rt")) {
  505.       while (fgets(line, 99, rcfile)) {
  506.      if (*line == '#')
  507.         continue;
  508.      strcpy(saveline, line);
  509.      if (!process(line, 0, ATRC)) {
  510.         if (saveline[strlen(saveline) - 1] == '\n')
  511.            saveline[strlen(saveline) - 1] = 0;
  512.         printf("%%Unknown command '%s' in .igcrc file\n", saveline);
  513.      }
  514.       }
  515.    }
  516. }
  517.  
  518.  
  519.  
  520. void dopassword(first)
  521. char *first;
  522. {
  523.    strncpy(password, first, 18);
  524.    strcat(password, "\n");
  525.    password[20]=0;
  526. }
  527.  
  528.  
  529. void dologin(first)
  530. char *first;
  531. {
  532.    strncpy(login, first, 18);
  533.    strcat(login, "\n");
  534.    login[20]=0;
  535. }
  536.  
  537.  
  538.  
  539. void handletstp()
  540. {
  541.    signal(SIGTSTP, handletstp);
  542.    if (boardon)
  543.       suspend();
  544.    kill(getpid(), SIGSTOP);
  545.    if (boardon) {
  546.       unsuspend();
  547.       if (boardmode)
  548.      boardrefresh();
  549.       else
  550.      serverrefresh();
  551.    }
  552. }
  553.  
  554.  
  555. int startgame(n)
  556. int n;
  557. {
  558.    char str[100], str2[30];
  559.    int ret, gotmove;
  560.  
  561.    gotmove = 0;
  562.  
  563.    sprintf(str, "games %d\n", n);
  564.    sendstr(str);
  565.    do {
  566.       do {
  567.      ret = getmessage(&mesg, 0);
  568.      if (ret < 0)
  569.         handleterm();
  570.       }
  571.       while (!ret);
  572.       if (mesg.id == MOVE) {
  573.      if (mesg.movecount)
  574.         putstr("%Premature move.  Restart game.");
  575.      else
  576.         gotmove = 1;
  577.       }
  578.    }
  579.    while (mesg.id != GAMES);
  580.    if (mesg.gamecount != 1 || mesg.gamelist[0].gnum != n)
  581.       return -1;
  582.    if (mesg.gamelist[0].bsize > 19) {
  583.       putstr("%Boardsize too large");
  584.       return -1;
  585.    }
  586.    strcpy(curgame.white, mesg.gamelist[0].white);
  587.    strcpy(curgame.black, mesg.gamelist[0].black);
  588.    strcpy(curgame.brank, mesg.gamelist[0].brank);
  589.    strcpy(curgame.wrank, mesg.gamelist[0].wrank);
  590.    curgame.hcap = mesg.gamelist[0].hcap;
  591.    curgame.komi = mesg.gamelist[0].komi;
  592.    if (observing) {
  593.       addstring("Removing observe\n");
  594.       sprintf(str, "observe %d\n", ingame);
  595.       sendstr(str);
  596.       do {
  597.      do {
  598.         ret = getmessage(&mesg, 0);
  599.         if (ret < 0)
  600.            handleterm();
  601.      }
  602.      while (!ret);
  603.       }
  604.       while (mesg.id != PROMPT);
  605.       observing = 0;
  606.    }
  607.    ingame = n;
  608.    needrestore = 0;
  609.    initboard(mesg.gamelist[0].bsize);
  610.    displaygamenumber(ingame);
  611.    xcur = ycur = mesg.gamelist[0].bsize / 2;
  612.    sprintf(str, "%s (%s)", curgame.black, curgame.brank);
  613.    sprintf(str2, "%s (%s)", curgame.white, curgame.wrank);
  614.    boardtitle(str, str2);
  615.    if (gotmove)
  616.       highlight(0, 0, 0, 0, mesg.btime, mesg.bbyo, mesg.wtime, mesg.wbyo);
  617.    showkomi(curgame.komi);
  618.    boardon = 1;
  619.    return 0;
  620. }
  621.  
  622.  
  623. getmoves(n)
  624. int n;
  625. {
  626.    char str[20];
  627.  
  628.    sprintf(str, "moves %d\n", n);
  629.    sendstr(str);
  630. }
  631.  
  632.  
  633. unobserve()
  634. {
  635.    sendstr("unobserve\n");
  636.    /* char str[20]; sprintf(str, "observe %d\n", ingame); sendstr(str); */
  637. }
  638.  
  639.  
  640. int observegame(n)
  641. int n;
  642. {
  643.    int ret;
  644.    char str[20];
  645.    if (n < 0)
  646.       return 1;
  647.    if (startgame(n))
  648.       return 1;
  649.    sprintf(str, "observe %d\n", n);
  650.    sendstr(str);
  651.    observing = 1;
  652.    do {
  653.       do {
  654.      ret = getmessage(&mesg, 0);
  655.      if (ret < 0)
  656.         handleterm();
  657.       }
  658.       while (!ret);
  659.       if ((mesg.id == INFO) && !strncmp(mesg.text, "Removing", 8))
  660.      putstr("%fatal sync error.  Restart igc.");
  661.    }
  662.    while (mesg.id != MOVE && mesg.id != UNDO);
  663.    getmoves(n);
  664.    return 0;
  665. }
  666.  
  667.  
  668. int peekgame(n)
  669. int n;
  670. {
  671.    /* if (!observing && ingame != -1) { putstr("Can't peek while playing.");
  672.     * return 1; } */
  673.    if (startgame(n))
  674.       return 1;
  675.    getmoves(n);
  676.    justpeeked = 1;
  677.    setgame(-1);
  678.    return 0;
  679. }
  680.  
  681. setgame(newgame)
  682. int newgame;
  683. {
  684.    if (newgame != ingame) {
  685.       ingame = newgame;
  686.       displaygamenumber(ingame);
  687.    }
  688. }
  689.  
  690. loadgame(name)
  691. char *name;
  692. {
  693.    char str[100];
  694.    int ret;
  695.    sprintf(str, "load %s\n", name);
  696.    sendstr(str);
  697.    do {
  698.       ret = getmessage(&mesg, 0);
  699.       if (ret < 0)
  700.      handleterm();
  701.    } while ((!ret) ||
  702.         (mesg.id != MOVE && mesg.id != ERROR && mesg.id != PROMPT));
  703.    if (mesg.id == ERROR)
  704.       putstr(mesg.text);
  705.    else if (mesg.id == PROMPT)
  706.       putstr("%Load error.");
  707.    else {
  708.       if (!startgame(mesg.gamenum))
  709.      getmoves(mesg.gamenum);
  710.    }
  711. }
  712.  
  713. char *helpmsg = "                   Server Window\n\
  714. unobserve      Stops observing.\n\
  715. peek <n>       Looks at the board for game n\n\
  716. restore        Restores active game (after look or status)\n\
  717. noboard        Goes back to full screen mode\n\
  718. clear          Clears the window on the right side of the screen\n\
  719. [no]inverse    Switches board to/from inverse \n\
  720. [no]invedge    Turns on/off inversed edges\n\
  721. [no]piecemarks Turns on/off piece marks\n\
  722. [no]edgemarks  Turns on/off edge marks\n\
  723. sort {none|rank|rating|game|name|idle} Chooses sorting order for who command\n\
  724. gamessort {none|number|obcount} Chooses sorting order for games command\n\
  725. user <name>    Checks output from last who for <name>\n\
  726. chars <list>   Sets board characters in client\n\
  727. border <char>  Sets the border character\n\
  728. beeps <n>      Sets number of beeps to use\n\
  729. [no]saybeep    Turns on/off beeps when a say is received\n\
  730. [no]tellbeep   Turns on/off beeps when a tell is received\n\
  731. goto <n>       Goes to a particular move in the current game.\n\
  732. [no]filter     Turn filtering of shouts on/off\n\
  733. [un]friend     Add or remove a name from the friends list\n\
  734. prefix         Sets prefix for all outgoing text you type\n\
  735.                Start commands with '!' to avoid using the prefix\n\
  736. \n\
  737. ESC switches between windows         ^L  refreshes the screen\n\
  738. \n\
  739.                    Board Window\n\
  740. Use number keys (12346789), emacs keys (^P ^N ^F ^B) or rogue keys\n\
  741.    (hjklbnyu) to move the cursor.\n\
  742. Press '0', return, or space to move (send position of cursor)\n\
  743. Press '.' or '>' to move forward through game, ',' or '<' to move backwards.\n\
  744.   '.' and ',' move by single moves.  '>' and '<' move by sets of ten moves.\n\
  745. Press 's' to go to start of game, 'e' to go to end.\n\
  746. Press 'f' or '/' to find the a particular move in a game by location.\n\
  747. Press 'c' to clear the current move mark.";
  748.  
  749.  
  750. void help()
  751. {
  752.    if (boardon)
  753.       bigmess(33, helpmsg);
  754.    else
  755.       puts(helpmsg);
  756. }
  757.  
  758.  
  759. doargs(argc, argv)
  760. int argc;
  761. char *argv[];
  762. {
  763.    int i;
  764.    for (i = 1; i < argc; i++) {
  765.       if (!strcmp(argv[i], "-s")) {
  766.      int j;
  767.      for (j = i; j < 3; j++)
  768.         argv[j] = argv[j + 1];
  769.      strcpy(login, "");
  770.      strcpy(password, "");
  771.      argc--;
  772.      break;
  773.       }
  774.    }
  775.    if (argc > 3) {
  776.       printf("Too many command line arguments\n\n");
  777.       exit(3);
  778.    }
  779.    if (argc > 1) {
  780.       for (i = 0; i < 10; i++)
  781.      if (!strcmp(argv[1], sitetable[i].name)) {
  782.         sethost(sitetable[i].site);
  783.         setport(sitetable[i].port);
  784.         if (argc > 2) {
  785.            printf("Error: port specified with named host.  Don't use a port number\n");
  786.            printf("when using the shorthand name for a host.\n\n");
  787.            exit(3);
  788.         }
  789.         return;
  790.      }
  791.       sethost(argv[1]);
  792.       if (argc > 2) {
  793.      if (atoi(argv[2]))
  794.         setport(atoi(argv[2]));
  795.      else {
  796.         printf("Illegal port specification\n\n");
  797.         exit(3);
  798.      }
  799.       }
  800.    }
  801. }
  802.  
  803.  
  804. weave()
  805. {
  806.    char *copy[MAXWHO];
  807.    int i, num;
  808.    num = mesg.whocount / 2 + (mesg.whocount & 1);
  809.    for (i = 0; i < num * 2; i++)
  810.       copy[i] = mesg.who[i];
  811.    for (i = 0; i < num; i++) {
  812.       mesg.who[2 * i] = copy[i];
  813.       mesg.who[2 * i + 1] = copy[num + i];
  814.    }
  815. }
  816.  
  817.  
  818. #define NAMECOL 12
  819. #define IDLECOL 25
  820. #define RANKCOL 32
  821. #define RATECOL 33
  822. #define FLAGCOL 2
  823. #define GAMECOL 10
  824.  
  825.  
  826. int namesort(left, right)
  827. char *left, *right;
  828. {
  829.    return strncasecmp(*(char **) left + NAMECOL, *(char **) right + NAMECOL, 11);
  830. }
  831.  
  832.  
  833. int gamesort(left, right)
  834. char *left, *right;
  835. {
  836.    int i;
  837.    char *a, *b;
  838.    a = *(char **) left;
  839.    b = *(char **) right;
  840.    if (a[GAMECOL] != '-' && b[GAMECOL] != '-') {
  841.       i = strncmp(a + GAMECOL - 2, b + GAMECOL - 2, 3);
  842.       return i ? i : namesort(left, right);
  843.    }
  844.    if (a[GAMECOL] != '-')
  845.       return -1;
  846.    if (b[GAMECOL] != '-')
  847.       return 1;
  848.    if (a[FLAGCOL] != b[FLAGCOL]) {
  849.       if (a[FLAGCOL] == 'X')
  850.      return -1;
  851.       if (b[FLAGCOL] == 'X')
  852.      return 1;
  853.       if (a[FLAGCOL] == '!')
  854.      return 1;
  855.       if (b[FLAGCOL] == '!')
  856.      return -1;
  857.    }
  858.    return ranksort(left, right);
  859. }
  860.  
  861.  
  862. int ratingsort(left, right)
  863. char *left, *right;
  864. {
  865.    char *a, *b;
  866.    a = *(char **) left;
  867.    b = *(char **) right;
  868.    if (a[RATECOL] == b[RATECOL])
  869.       return ranksort(left, right);
  870.    if (a[RATECOL] == '*')
  871.       return -1;
  872.    return 1;
  873. }
  874.  
  875.  
  876. int ranksort(left, right)
  877. char *left, *right;
  878. {
  879.    int i;
  880.    char *a, *b;
  881.  
  882.    a = *(char **) left;
  883.    b = *(char **) right;
  884.  
  885.    if (a[RANKCOL] == '2')
  886.       return -1;
  887.    if (b[RANKCOL] == '2')
  888.       return 1;
  889.    if (a[RANKCOL] != b[RANKCOL]) {
  890.       if (a[RANKCOL] == '?')
  891.      return 1;
  892.       if (b[RANKCOL] == '?')
  893.      return -1;
  894.       if (a[RANKCOL] == 'R')
  895.      return 1;
  896.       if (b[RANKCOL] == 'R')
  897.      return -1;
  898.       if (a[RANKCOL] == 'k')
  899.      return 1;
  900.       if (b[RANKCOL] == 'k')
  901.      return -1;
  902.       if (a[RANKCOL] == 'd')
  903.      return 1;
  904.       if (b[RANKCOL] == 'd')
  905.      return -1;
  906.       return namesort(a, b);
  907.    }
  908.    if (a[RANKCOL] == 'R' || a[RANKCOL] == '?')
  909.       return namesort(left, right);
  910.    i = atoi(a + RANKCOL - 2) - atoi(b + RANKCOL - 2);
  911.    if (a[RANKCOL] == 'k')
  912.       i = -i;
  913.    return i ? -i : namesort(left, right);
  914. }
  915.  
  916.  
  917. /*******************
  918.  * idlesort  decides whether a or b has been idle longer
  919.  *******************/
  920.  
  921. int idlesort(left, right)
  922. char *left, *right;
  923. {
  924.    int i;
  925.    char *a, *b;
  926.  
  927.    a = *(char **) left;
  928.    b = *(char **) right;
  929.  
  930.    /* first check the units letter (h,m,s) assume that we don't need to worry
  931.     * about d. */
  932.    if (a[IDLECOL] != b[IDLECOL]) {
  933.       if (a[IDLECOL] == 'h')
  934.      return -1;
  935.       if (b[IDLECOL] == 'h')
  936.      return 1;
  937.       if (a[IDLECOL] == 'm')
  938.      return -1;
  939.       if (b[IDLECOL] == 'm')
  940.      return 1;
  941.    }
  942.    i = atoi(b + IDLECOL - 2) - atoi(a + IDLECOL - 2);
  943.    return i ? i : namesort(left, right);
  944. }
  945.  
  946.  
  947. int gamenumsort(a, b)
  948. struct gametype *a;
  949. struct gametype *b;
  950. {
  951.    if (a->gnum < b->gnum)
  952.       return -1;
  953.    if (a->gnum > b->gnum)
  954.       return 1;
  955.    return 0;
  956. }
  957.  
  958. int gamesobsort(a, b)
  959. struct gametype *a;
  960. struct gametype *b;
  961. {
  962.    if (a->obcount > b->obcount)
  963.       return -1;
  964.    if (a->obcount < b->obcount)
  965.       return 1;
  966.    return 0;
  967. }
  968.  
  969.  
  970.  
  971. int choosegamessort(first)
  972. char *first;
  973. {
  974.    if (!first)
  975.       return 1;
  976.    if (!strcmp(first, "number")) {
  977.       gamessort = gamenumsort;
  978.       return 0;
  979.    }
  980.    if (!strcmp(first, "none")) {
  981.       gamessort = NULL;
  982.       return 0;
  983.    }
  984.    if (!strcmp(first, "obcount")) {
  985.       gamessort = gamesobsort;
  986.       return 0;
  987.    }
  988.    return 1;
  989. }
  990.  
  991.  
  992. int choosesort(first)
  993. char *first;
  994. {
  995.    if (!first)
  996.       return 1;
  997.    if (!strcmp(first, "name")) {
  998.       whosort = namesort;
  999.       return 0;
  1000.    }
  1001.    if (!strcmp(first, "rank")) {
  1002.       whosort = ranksort;
  1003.       return 0;
  1004.    }
  1005.    if (!strcmp(first, "game")) {
  1006.       whosort = gamesort;
  1007.       return 0;
  1008.    }
  1009.    if (!strcmp(first, "none")) {
  1010.       whosort = 0;
  1011.       return 0;
  1012.    }
  1013.    if (!strcmp(first, "idle")) {
  1014.       whosort = idlesort;
  1015.       return 0;
  1016.    }
  1017.    if (!strcmp(first, "rating")) {
  1018.       whosort = ratingsort;
  1019.       return 0;
  1020.    }
  1021.    return 1;
  1022. }
  1023.  
  1024.  
  1025. restoregame()
  1026. {
  1027.    char str[30], str2[30];
  1028.  
  1029.    if (needrestore) {
  1030.       if (bschange)
  1031.      initboard(bschange);
  1032.       restoremaxmoves();
  1033.       endgame();
  1034.       needrestore = 0;
  1035.       sprintf(str, "%s (%s)", curgame.black, curgame.brank);
  1036.       sprintf(str2, "%s (%s)", curgame.white, curgame.wrank);
  1037.       boardtitle(str, str2);
  1038.       highlight(0, 0, 0, -1, curgame.btime, curgame.bbyo,
  1039.         curgame.wtime, curgame.wbyo);
  1040.       displaygamenumber(ingame);
  1041.    }
  1042. }
  1043.  
  1044.  
  1045. void dofilter(first)
  1046. int first;
  1047. {
  1048.    friendfilter = first;
  1049. }
  1050.  
  1051.  
  1052.  
  1053. void dofriend(who)
  1054. char *who;
  1055. {
  1056.    int i;
  1057.    char buff[60];
  1058.  
  1059.    if (!who) {
  1060.       putstr("%Current list of friends:\n");
  1061.       for (i = 0; i < nfriends; i++)
  1062.      putstr(friend[i]);
  1063.  
  1064.    } else {
  1065.       if (nfriends >= MAXFRIENDS)
  1066.      putstr("%Friend list is full.");
  1067.       else if (-1 != find_friend(who)) {
  1068.      sprintf(buff, "%%Player %s already in friend list.", who);
  1069.      putstr(buff);
  1070.       } else {
  1071.      strcpy(friend[nfriends], who);
  1072.      nfriends++;
  1073.      sprintf(buff, "%%Friend %s added.", who);
  1074.      putstr(buff);
  1075.       }
  1076.    }
  1077. }
  1078.  
  1079.  
  1080. int isfriend(text)
  1081. char *text;
  1082. {
  1083.    int i, length;
  1084.  
  1085.    if (*text != '{')
  1086.       return 1;
  1087.    text++;
  1088.    for (i = 0; i < nfriends; i++) {
  1089.       length = strlen(friend[i]);
  1090.       if (!strncmp(friend[i], text, length) && text[length] == ' ')
  1091.      return 1;
  1092.    }
  1093.    return 0;
  1094. }
  1095.  
  1096.  
  1097.  
  1098. void dounfriend(who)
  1099. char *who;
  1100. {
  1101.    char i;
  1102.  
  1103.    if (!who)
  1104.       putstr("%unfriend requires 1 parameter.");
  1105.    else if (-1 != (i = find_friend(who))) {
  1106.       for (; i < nfriends; i++)
  1107.      strcpy(friend[i], friend[i + 1]);
  1108.       nfriends--;
  1109.       putstr("%Friend removed.");
  1110.    } else
  1111.       putstr("%Friend not in list.");
  1112. }
  1113.  
  1114.  
  1115. int find_friend(fr)
  1116. char *fr;
  1117. {
  1118.    char i;
  1119.  
  1120.    for (i = 0; i < nfriends && strcmp(friend[i], fr); i++);
  1121.    return i == nfriends ? -1 : i;
  1122. }
  1123.  
  1124.  
  1125. main(argc, argv)
  1126. int argc;
  1127. char *argv[];
  1128. {
  1129.    char ch;
  1130.    int ret;
  1131.    puts("\tigc - Ascii Client version 0.70 by Adrian Mariano");
  1132.    puts("   type 'helpigc' to get client help, 'help' for server help\n");
  1133.    strcpy(prefix, "");
  1134.    whosort = namesort;
  1135.    gamessort = gamenumsort;
  1136.    readrc();
  1137.    sethost(sitetable[0].site);
  1138.    setport(sitetable[0].port);
  1139.    doargs(argc, argv);
  1140.    loc = local;
  1141.    signal(SIGINT, handleterm);
  1142.    signal(SIGTERM, handleterm);
  1143.    signal(SIGHUP, handleterm);
  1144.    signal(SIGTSTP, handletstp);
  1145.    if (open_connection())
  1146.       handleterm();
  1147.    puts("Connection established.");
  1148.    mesg.whocount = 0;
  1149.    {
  1150.       char *whoptr;
  1151.       for (whoptr = &(mesg.whodata[0][0]), ret = 0; ret < MAXWHO; ret++, whoptr += 40)
  1152.      mesg.who[ret] = whoptr;
  1153.    }
  1154.    initparser();
  1155.    do {
  1156.       if (boardon)
  1157.      if (boardmode)
  1158.         boardrefresh();
  1159.      else
  1160.         serverrefresh();
  1161.       ret = getmessage(&mesg, 1);
  1162.       if (ret < 0 && ret != KEY) {
  1163.      if (boardon) {
  1164.         endAscii();
  1165.         boardon = 0;
  1166.      }
  1167.      puts("Connection closed by server.");
  1168.      myexit(0);
  1169.       }
  1170.       if (ret > 0)
  1171.      switch (mesg.id) {
  1172.         case TOOMANY:
  1173.            myexit(0);
  1174.            printf("Too many players.  Sorry.\n");
  1175.            break;
  1176.         case QUITMESG:
  1177.            if (boardon) {
  1178.           endAscii();
  1179.           boardon = 0;
  1180.            }
  1181.            puts(mesg.text);
  1182.            break;
  1183.         case ONSERVER:
  1184.            printf("\nWarning: Client mode is not set on the IGS.  Setting client mode now.\n         The message of the day was not displayed.  Type 'help motd' to see it.\n         You have not been informed if you have messages.\n\n");
  1185.  
  1186.            break;
  1187.         case BEEP:
  1188.            if (mesg.beep)
  1189.           dobeep();
  1190.            break;
  1191.         case MOVE:
  1192.            if (!boardon)
  1193.           puts("%Error: isolated move received");
  1194.            else {
  1195.           int i;
  1196.           restoregame();
  1197.           sethighlight(0);
  1198.           for (i = 0; i < mesg.movecount - 1; i++)
  1199.              makemove(mesg.moves[i].x, mesg.moves[i].y,
  1200.                   mesg.moves[i].movenum,
  1201.                   mesg.moves[i].color, mesg.btime,
  1202.                   mesg.bbyo, mesg.wtime, mesg.wbyo);
  1203.           sethighlight(1);
  1204.           if (mesg.movecount)
  1205.              makemove(mesg.moves[i].x, mesg.moves[i].y,
  1206.                   mesg.moves[i].movenum,
  1207.                   mesg.moves[i].color, mesg.btime,
  1208.                   mesg.bbyo, mesg.wtime, mesg.wbyo);
  1209.           curgame.bbyo = mesg.bbyo;
  1210.           curgame.btime = mesg.btime;
  1211.           curgame.wtime = mesg.wtime;
  1212.           curgame.wbyo = mesg.wbyo;
  1213.  
  1214.  
  1215.           setcursor(xcur, ycur);
  1216.           if (!justpeeked)
  1217.              setgame(mesg.gamenum);
  1218.           justpeeked = 0;
  1219.            }
  1220.            break;
  1221.         case UNDO:
  1222.            restoregame();
  1223.            if (!boardon)
  1224.           puts("%Error: isolated undo received");
  1225.            else {
  1226.           setgame(mesg.gamenum);
  1227.           undo();
  1228.           setcursor(xcur, ycur);
  1229.            }
  1230.            break;
  1231.         case SCOREUNDO:
  1232.            restoregame();
  1233.            if (endgame())
  1234.           putstr("%score undo error");
  1235.            else
  1236.           putstr("Scoring undone.");
  1237.            break;
  1238.         case LOAD:
  1239.            if (!startgame(mesg.gamenum))
  1240.           getmoves(mesg.gamenum);
  1241.            break;
  1242.         case MATCH:
  1243.            startgame(mesg.gamenum);
  1244.            break;
  1245.         case REMOVE:
  1246.            restoregame();
  1247.            removeGroup(mesg.x, mesg.y);
  1248.            setcursor(xcur, ycur);
  1249.            break;
  1250.         case SCORE:
  1251.            {
  1252.           char str[50];
  1253.           sprintf(str, "  %s (B): %g\n  %s (W): %g",
  1254.               mesg.black, mesg.bscore, mesg.white, mesg.wscore);
  1255.           putstr(str);
  1256.            }
  1257.            break;
  1258.         case STARTSCORE:
  1259.            putstr("Remove dead groups to score.");
  1260.            putstr(mesg.text);
  1261.            break;
  1262.         case STATUS:
  1263.         case LOOK:
  1264.            {
  1265.           int pris[2];
  1266.           char str[30], str2[30];
  1267.  
  1268.           if (mesg.boardsize > 19)
  1269.              putstr("%Boardsize too big.");
  1270.           else {
  1271.              needrestore = 1;
  1272.              bschange = 0;
  1273.              savemaxmoves();
  1274.              if (!boardon || boardsize != mesg.boardsize) {
  1275.             if (!boardon)
  1276.                needrestore = 0;
  1277.             else
  1278.                bschange = boardsize;
  1279.             initboard(mesg.boardsize);
  1280.             xcur = ycur = mesg.boardsize / 2;
  1281.             boardon = 1;
  1282.              }
  1283.              pris[0] = mesg.bcap;
  1284.              pris[1] = mesg.wcap;
  1285.              sprintf(str, "%s (%s)", mesg.black, mesg.brank);
  1286.              sprintf(str2, "%s (%s)", mesg.white, mesg.wrank);
  1287.              boardtitle(str, str2);
  1288.              highlight(0, 0, 0, -1, mesg.btime, mesg.bbyo,
  1289.                    mesg.wtime, mesg.wbyo);
  1290.              drawpris(pris);
  1291.              showboard(mesg.board);
  1292.              displaygamenumber(-2);
  1293.           }
  1294.            }
  1295.            break;
  1296.         case KIBITZ:
  1297.            {
  1298.           char s[300];
  1299.           sprintf(s, "%s: %s", mesg.kibitzer, mesg.kibitz);
  1300.           putstr(s);
  1301.            }
  1302.            break;
  1303.         case WHO:
  1304.            {
  1305.           char out[80 * MAXWHO];
  1306.           int i;
  1307.           if (whosort) {
  1308.              qsort(mesg.who, mesg.whocount, sizeof(char *), whosort);
  1309.              weave();
  1310.           }
  1311.           strcpy(out, mesg.whofirst);
  1312.           for (i = 0; i < mesg.whocount; i++) {
  1313.              strcat(out, i & 1 ? " | " : "\n");
  1314.              strcat(out, mesg.who[i]);
  1315.           }
  1316.           strcat(out, "\n");
  1317.           strcat(out, mesg.wholast);
  1318.           if (boardon)
  1319.              bigmess(mesg.lines, out);
  1320.           else
  1321.              putstr(out);
  1322.            }
  1323.            break;
  1324.         case GAMES:
  1325.            {
  1326.           char out[80 * MAXGAMES];
  1327.           int i;
  1328.           if (gamessort)
  1329.              qsort(mesg.gamelist, mesg.gamecount, sizeof(struct gametype), gamessort);
  1330.           strcpy(out, mesg.gamefirst);
  1331.           strcat(out, "\n");
  1332.           for (i = 0; i < mesg.gamecount; i++)
  1333.              strcat(out, mesg.gamelist[i].gametext);
  1334.           if (boardon)
  1335.              bigmess(mesg.gamecount + 1, out);
  1336.           else
  1337.              putstr(out);
  1338.            }
  1339.            break;
  1340.         case STORED:
  1341.            if (!strlen(mesg.text))
  1342.           putstr("No stored games");
  1343.            else
  1344.           putstr(mesg.text);
  1345.            break;
  1346.         case CHKOMI:
  1347.            curgame.komi = mesg.mykomi;
  1348.            showkomi(curgame.komi);
  1349.         case INFO:
  1350.            if (strstr(mesg.text, "Removing")) {
  1351.           observing = 0;
  1352.           setgame(-1);
  1353.           putstr(mesg.text);
  1354.            } else if (mesg.lines > 1 && boardon)
  1355.           bigmess(mesg.lines, mesg.text);
  1356.            else if (strlen(mesg.text))
  1357.           putstr(mesg.text);
  1358.            break;
  1359.         case PROMPT:
  1360.            if (ingame != -1 && mesg.prompttype == 5) {
  1361.           setgame(-1);
  1362.           observing = 0;
  1363.            }
  1364.            break;
  1365.             case ENDGAMEINFO:
  1366.                if (observing && mesg.gamenum == ingame){
  1367.                   setgame(-1);
  1368.                   observing = 0;
  1369.                }
  1370.                putstr(mesg.text);
  1371.            break;
  1372.             case ENDGAME:
  1373.                if (observing && mesg.gamenum == ingame){
  1374.           setgame(-1);
  1375.           observing = 0;
  1376.                }
  1377.         case SHOUT:
  1378.            if (!friendfilter || isfriend(mesg.text))
  1379.           putstr(mesg.text);
  1380.            break;
  1381.  
  1382.         case SAY:
  1383.            if (saybeep)
  1384.           dobeep();
  1385.            putstr(mesg.text);
  1386.            break;
  1387.         case TELL:
  1388.            if (tellbeep)
  1389.           dobeep();
  1390.            putstr(mesg.text);
  1391.            break;
  1392.         case 0:
  1393.            break;
  1394.             case INTRO:
  1395.                if (!displayintro) 
  1396.                   break;
  1397.         default:
  1398.            if (mesg.lines > 1 && boardon)
  1399.           bigmess(mesg.lines, mesg.text);
  1400.            else if (strlen(mesg.text))
  1401.           putstr(mesg.text);
  1402.            break;
  1403.      }
  1404.       if (ret == KEY) {
  1405.      ret = read(fileno(stdin), &ch, 1);
  1406.      if (ch == '\r')
  1407.         ch = '\n';
  1408.      if (ch == 'L' - 64 && boardon)
  1409.         redraw();
  1410.      else if (ch == 27 && boardon)
  1411.         switchmode();
  1412.      else if (boardmode)
  1413.         doboardmode(ch);
  1414.      else
  1415.         doservermode(ch);
  1416.       }
  1417.    }
  1418.    while (1);
  1419.    handleterm();
  1420. }
  1421.  
  1422.  
  1423. switchmode()
  1424. {
  1425.    boardmode = !boardmode;
  1426.    if (boardmode)
  1427.       setcursor(xcur, ycur);
  1428. }
  1429.  
  1430.  
  1431. static char *nomoves = "%no moves recorded";
  1432.  
  1433. doboardmode(ch)
  1434. char ch;
  1435. {
  1436.    char movestr[10];
  1437.    switch (ch) {
  1438.       case '^':
  1439.      switchmode();
  1440.      clearserver();
  1441.      switchmode();
  1442.      break;
  1443.       case ',':
  1444.      restoregame();
  1445.      if (backward(1))
  1446.         putstr(nomoves);
  1447.      break;
  1448.       case '.':
  1449.      restoregame();
  1450.      if (forward(1))
  1451.         putstr(nomoves);
  1452.      break;
  1453.       case '<':
  1454.      restoregame();
  1455.      if (backward(10))
  1456.         putstr(nomoves);
  1457.      break;
  1458.       case '>':
  1459.      restoregame();
  1460.      if (forward(10))
  1461.         putstr(nomoves);
  1462.      break;
  1463.       case 's':
  1464.      restoregame();
  1465.      if (beginninggame())
  1466.         putstr(nomoves);
  1467.      break;
  1468.       case 'e':
  1469.      restoregame();
  1470.      if (endgame())
  1471.         putstr(nomoves);
  1472.      break;
  1473.       case 'f':
  1474.       case '/':
  1475.      restoregame();
  1476.      if (search(xcur, ycur))
  1477.         putstr("%No move found at that point");
  1478.      break;
  1479.  
  1480.       case '1':
  1481.       case 'b':
  1482.      if (++ycur == boardsize)
  1483.         ycur = 0;
  1484.      if (!xcur--)
  1485.         xcur = boardsize - 1;
  1486.      break;
  1487.       case '3':
  1488.       case 'n':
  1489.      if (++ycur == boardsize)
  1490.         ycur = 0;
  1491.      if (++xcur == boardsize)
  1492.         xcur = 0;
  1493.      break;
  1494.       case '7':
  1495.       case 'y':
  1496.      if (!xcur--)
  1497.         xcur = boardsize - 1;
  1498.      if (!ycur--)
  1499.         ycur = boardsize - 1;
  1500.      break;
  1501.       case '9':
  1502.       case 'u':
  1503.      if (!ycur--)
  1504.         ycur = boardsize - 1;
  1505.      if (++xcur == boardsize)
  1506.         xcur = 0;
  1507.      break;
  1508.       case 'B' - 64:
  1509.       case '4':
  1510.       case 'h':
  1511.  
  1512.      if (!xcur--)
  1513.         xcur = boardsize - 1;
  1514.      break;
  1515.       case 'P' - 64:
  1516.       case '8':
  1517.       case 'k':
  1518.      if (!ycur--)
  1519.         ycur = boardsize - 1;
  1520.      break;
  1521.       case 'N' - 64:
  1522.       case '2':
  1523.       case 'j':
  1524.      if (++ycur == boardsize)
  1525.         ycur = 0;
  1526.      break;
  1527.       case 'F' - 64:
  1528.       case '6':
  1529.       case 'l':
  1530.      if (++xcur == boardsize)
  1531.         xcur = 0;
  1532.      break;
  1533.       case 'c':
  1534.      unmark();
  1535.      break;
  1536.       case '\n':
  1537.       case '\r':
  1538.       case ' ':
  1539.       case '0':
  1540.      sprintf(movestr, "%c%d\n", xcur + 'A' + (xcur + 'A' >= 'I' ? 1 : 0),
  1541.          boardsize - ycur);
  1542.      sendstr(movestr);
  1543.      break;
  1544.    }
  1545.    setcursor(xcur, ycur);
  1546. }
  1547.  
  1548.  
  1549. void dopeek(first)
  1550. char *first;
  1551. {
  1552.    if (first) {
  1553.       if (!observing && ingame != -1)
  1554.      putstr("%Can't observe while playing");
  1555.       else if (observing && ingame == atoi(first))
  1556.      unobserve();
  1557.       else if (peekgame(atoi(first)))
  1558.      putstr("%No such game");
  1559.    }
  1560. }
  1561.  
  1562.  
  1563. void doobserve(first)
  1564. char *first;
  1565. {
  1566.    if (first) {
  1567.       if (!observing && ingame != -1)
  1568.      putstr("%Can't observe while playing");
  1569.       else if (observing && ingame == atoi(first))
  1570.      unobserve();
  1571.       else if (observegame(atoi(first)))
  1572.      putstr("%No such game");
  1573.    }
  1574. }
  1575.  
  1576.  
  1577. void dounobserve()
  1578. {
  1579.    if (observing)
  1580.       unobserve();
  1581.    else
  1582.       putstr("%Not observing");
  1583. }
  1584.  
  1585.  
  1586. void doload(first)
  1587. char *first;
  1588. {
  1589.    if (first)
  1590.       loadgame(first);
  1591. }
  1592.  
  1593.  
  1594. void dochars(first)
  1595. char *first;
  1596. {
  1597.    if (first) {
  1598.       setchars(first);
  1599.       if (boardon) {
  1600.      reinitboard(boardsize);
  1601.      endgame();
  1602.       }
  1603.    }
  1604. }
  1605.  
  1606.  
  1607. void dorestore(first)
  1608. char *first;
  1609. {
  1610.    if (!needrestore)
  1611.       putstr("%no game to restore");
  1612.    restoregame();
  1613. }
  1614.  
  1615.  
  1616. void dosort(first)
  1617. char *first;
  1618. {
  1619.    if (choosesort(first))
  1620.       putstr("%Unknown sorting method");
  1621. }
  1622.  
  1623.  
  1624. void dogamessort(first)
  1625. char *first;
  1626. {
  1627.    if (choosegamessort(first))
  1628.       putstr("%Unknown games sorting method");
  1629. }
  1630.  
  1631.  
  1632.  
  1633. void doborder(first)
  1634. char *first;
  1635. {
  1636.    if (!first)
  1637.       setborder(' ');
  1638.    else
  1639.       setborder(*first);
  1640.    if (boardon) {
  1641.       reinitboard(boardsize);
  1642.       endgame();
  1643.    }
  1644. }
  1645.  
  1646.  
  1647. void dointro(first)
  1648. int first;
  1649. {
  1650.    displayintro=first;
  1651. }
  1652.  
  1653.  
  1654. void doinverse(first)
  1655. int first;
  1656. {
  1657.    setinverse(first);
  1658.    if (boardon) {
  1659.       reinitboard(boardsize);
  1660.       endgame();
  1661.    }
  1662. }
  1663.  
  1664.  
  1665. void doedgemarks(first)
  1666. int first;
  1667. {
  1668.    setedgemark(first);
  1669.    if (boardon) {
  1670.       reinitboard(boardsize);
  1671.       endgame();
  1672.    }
  1673. }
  1674.  
  1675. void dopiecemarks(first)
  1676. int first;
  1677. {
  1678.    setpiecemark(first);
  1679.    if (boardon) {
  1680.       reinitboard(boardsize);
  1681.       endgame();
  1682.    }
  1683. }
  1684.  
  1685.  
  1686.  
  1687. void doinvedge(first)
  1688. int first;
  1689. {
  1690.    setinverseborder(first);
  1691.    if (boardon) {
  1692.       reinitboard(boardsize);
  1693.       endgame();
  1694.    }
  1695. }
  1696.  
  1697.  
  1698. void doprefix(first)
  1699. char *first;
  1700. {
  1701.    if (!first)
  1702.       strcpy(prefix, "");
  1703.    else {
  1704.       strncpy(prefix, first, 19);
  1705.       prefix[20] = 0;
  1706.    }
  1707.  
  1708.    if (boardon)
  1709.       showprefix(prefix);
  1710.    else
  1711.       printf("Prefix '%s'\n", prefix);
  1712. }
  1713.  
  1714. void douser(first)
  1715. char *first;
  1716. {
  1717.    int i, found;
  1718.  
  1719.    if (!first)
  1720.       putstr("%No user specified");
  1721.    else {
  1722.       found = 0;
  1723.       for (i = 0; i < mesg.whocount; i++) {
  1724.      if (!strncmp(mesg.who[i] + NAMECOL, first, strlen(first)) &&
  1725.          mesg.who[i][NAMECOL + strlen(first)] == ' ') {
  1726.         putstr(mesg.who[i]);
  1727.         found = 1;
  1728.      }
  1729.       }
  1730.       if (!found)
  1731.      putstr("%User not found in last who");
  1732.    }
  1733. }
  1734.  
  1735.  
  1736. void dosaybeep(first)
  1737. int first;
  1738. {
  1739.    saybeep = first;
  1740. }
  1741.  
  1742.  
  1743. void dotellbeep(first)
  1744. int first;
  1745. {
  1746.    tellbeep = first;
  1747. }
  1748.  
  1749.  
  1750. void dobeeps(first)
  1751. char *first;
  1752. {
  1753.    if (first)
  1754.       beepcount = atoi(first);
  1755. }
  1756.  
  1757. void doclear(first)
  1758. char *first;
  1759. {
  1760.    if (!boardon)
  1761.       putstr("%Cannot clear.");
  1762.    else
  1763.       clearserver();
  1764. }
  1765.  
  1766. void donoboard(first)
  1767. char *first;
  1768. {
  1769.    if (boardon) {
  1770.       if (ingame != -1) {
  1771.      putstr("Board in use.  Cannot remove.");
  1772.       } else {
  1773.      boardon = 0;
  1774.      boardmode = 0;
  1775.      endAscii();
  1776.       }
  1777.    } else
  1778.       putstr("%No board to remove.");
  1779. }
  1780.  
  1781.  
  1782. void dogoto(first)
  1783. char *first;
  1784. {
  1785.    if (boardon) {
  1786.       first = strtok(NULL, " \t");
  1787.       if (first)
  1788.      construct(atoi(first));
  1789.    } else
  1790.       putstr("%no board");
  1791. }
  1792.  
  1793.  
  1794. /* Warning:  This function makes calls to strtok which assume that we've
  1795.  * already started parsing the input line. */
  1796.  
  1797. void dosite(first)
  1798. char *first;
  1799. {
  1800.    int num;
  1801.    char *next;
  1802.  
  1803.    num = atoi(first);
  1804.    if (num < 0 || num >= MAXSITES) {
  1805.       printf("%%invalid site number: %d\n", num);
  1806.       return;
  1807.    }
  1808.    next = strtok(NULL, " \t\n=");
  1809.    if (!next) {
  1810.       printf("%%invalid or missing site name in 'site %d'\n", num);
  1811.       return;
  1812.    }
  1813.    strcpy(sitetable[num].name, next);
  1814.    next = strtok(NULL, " \t\n=");
  1815.    if (!next) {
  1816.       printf("%%invalid or missing host name in 'site %d' command\n", num);
  1817.       return;
  1818.    }
  1819.    strcpy(sitetable[num].site, next);
  1820.    next = strtok(NULL, " \t\n=");
  1821.    if (next && atoi(next))
  1822.       sitetable[num].port = atoi(next);
  1823. }
  1824.  
  1825.  
  1826.  
  1827. int notfirst = 0;
  1828.  
  1829. doservermode(ch)
  1830. char ch;
  1831. {
  1832.    *loc = ch;
  1833.    *(loc + 1) = 0;
  1834.    if (ch < ' ' && ch != ('U' - 64) && ch != '\b' && ch != '\n')
  1835.       return;
  1836.    if (boardon) {
  1837.       if (*loc == '\b' || *loc == '\177') {
  1838.      if (strlen(local) > 1) {
  1839.         deletechar(strlen(local) - 2);
  1840.         loc -= 2;
  1841.      } else
  1842.         loc--;
  1843.       } else if (*loc == 'U' - 64) {
  1844.      loc = local;
  1845.      clrline();
  1846.      return;
  1847.       } else if (strlen(local) >= linesize()) {
  1848.      if (!notfirst)
  1849.         sendstr(prefix);
  1850.      sendstr(local);
  1851.      loc = local;
  1852.      notfirst = 1;
  1853.      clrline();
  1854.      putstr(local);
  1855.      return;
  1856.       } else
  1857.      addcharline(strlen(local) - 1, *loc);
  1858.    }
  1859.    if (*loc == '\n') {
  1860.       loc++;
  1861.       *loc = 0;
  1862.       if (boardon) {
  1863.      addstring(local);
  1864.       }
  1865.       if (notfirst)
  1866.      sendstr(local);
  1867.       else if (local[0] == '!')
  1868.      process(local + 1, 0, NOTATRC);
  1869.       else if (strlen(prefix)) {
  1870.      sendstr(prefix);
  1871.      sendstr(local);
  1872.       } else
  1873.      process(local, 1, NOTATRC);
  1874.       if (boardon)
  1875.      clrline();
  1876.       notfirst = 0;
  1877.       loc = local;
  1878.    } else
  1879.       loc++;
  1880. }
  1881.  
  1882.  
  1883.  
  1884.  
  1885.  
  1886. struct commandtype {
  1887.    char *command;
  1888.    void (*action) ();
  1889.    int inrc;
  1890.    int toggle;
  1891. }  comlist[] =
  1892. {
  1893.    { "border", doborder, BOTH, 0 },
  1894.    { "chars", dochars, BOTH, 0 },
  1895.    { "clear", doclear, NOTATRC, 0 },
  1896.    { "beeps", dobeeps, BOTH, 0 },
  1897.    { "edgemarks", doedgemarks, BOTH, 1 },
  1898.    { "filter", dofilter, BOTH, 1}, 
  1899.    { "friend", dofriend, BOTH, 0 }, 
  1900.    { "gamessort", dogamessort, BOTH, 0 },
  1901.    { "goto", dogoto, NOTATRC, 0 },
  1902.    { "helpigc", help, NOTATRC, 0 },
  1903.    { "intro", dointro, BOTH, 1}, 
  1904.    { "invedge", doinvedge, BOTH, 1 },
  1905.    { "inverse", doinverse, BOTH, 1 },
  1906.    { "loa", doload, NOTATRC, 0 },
  1907.    { "load", doload, NOTATRC, 0 },
  1908.    { "login", dologin, ATRC, 0 },
  1909.    { "mo", dopeek, NOTATRC, 0 },
  1910.    { "mov", dopeek, NOTATRC, 0 },
  1911.    { "move", dopeek, NOTATRC, 0 },
  1912.    { "moves", dopeek, NOTATRC, 0 },
  1913.    { "noboard", donoboard, NOTATRC, 0 },
  1914.    { "ob", doobserve, NOTATRC, 0 },
  1915.    { "obs", doobserve, NOTATRC, 0 },
  1916.    { "obse", doobserve, NOTATRC, 0 },
  1917.    { "obser", doobserve, NOTATRC, 0 },
  1918.    { "observ", doobserve, NOTATRC, 0 },
  1919.    { "observe", doobserve, NOTATRC, 0 },
  1920.    { "password", dopassword, ATRC, 0 },
  1921.    { "peek", dopeek, NOTATRC, 0 },
  1922.    { "piecemarks", dopiecemarks, BOTH, 1 },
  1923.    { "prefix", doprefix, NOTATRC, 0 },
  1924.    { "restore", dorestore, NOTATRC, 0 },
  1925.    { "saybeep", dosaybeep, BOTH, 1 },
  1926.    { "site", dosite, ATRC, 0}, 
  1927.    { "sort", dosort, BOTH, 0 },
  1928.    { "tellbeep", dotellbeep, BOTH, 1 },
  1929.    { "unfriend", dounfriend, BOTH, 0 }, 
  1930.    { "unob", dounobserve, NOTATRC, 0 },
  1931.    { "unobserve", dounobserve, NOTATRC, 0 },
  1932.    { "user", douser, NOTATRC, 0 }
  1933. };
  1934.  
  1935.  
  1936. /* Returns 1 if the command was parsed locally.  Returns 0 if the command was
  1937.  * passed the the server, or not parsed locally. */
  1938.  
  1939. int process(comm, dopre, state)
  1940. char *comm;
  1941. int dopre;
  1942. int state;
  1943. {
  1944.    char *first, *second;
  1945.    char save[1000];
  1946.    int i;
  1947.  
  1948.    strcpy(save, comm);
  1949.    first = strtok(comm, " \n\t=");
  1950.    second = strtok(NULL, " \n\t=");
  1951.    if (!first)
  1952.       return 1;
  1953.    for (i = 0; i < sizeof(comlist) / sizeof(struct commandtype); i++) {
  1954.       if ((state & comlist[i].inrc) &&
  1955.       !strcmp(first, comlist[i].command)) {
  1956.      if (comlist[i].toggle)
  1957.         comlist[i].action(1);
  1958.      else
  1959.         comlist[i].action(second);
  1960.      return 1;
  1961.       }
  1962.    }
  1963.    if (!strncmp(first, "no", 2)) {
  1964.       first += 2;
  1965.       for (i = 0; i < sizeof(comlist) / sizeof(struct commandtype); i++) {
  1966.      if ((state & comlist[i].inrc) && comlist[i].toggle &&
  1967.          !strcmp(first, comlist[i].command)) {
  1968.         comlist[i].action(0);
  1969.         return 1;
  1970.      }
  1971.       }
  1972.    }
  1973.    if (state == NOTATRC) {
  1974.       if (dopre)
  1975.      sendstr(prefix);
  1976.       sendstr(save);
  1977.    }
  1978.    return 0;
  1979. }
  1980. SHAR_EOF
  1981. fi
  1982. if test -f 'parse.c'
  1983. then
  1984.     echo shar: "will not over-write existing file 'parse.c'"
  1985. else
  1986. cat << \SHAR_EOF > 'parse.c'
  1987. #include "igc.h"
  1988. #include <stdio.h>
  1989. #include <string.h>
  1990. #include <sys/types.h>
  1991. #include "numbers.h"
  1992.  
  1993. extern char *getloginname();
  1994. extern char *getpassword();
  1995. int loggedon, verbosetog;
  1996. int repeatpass, repeatlogin;
  1997.  
  1998. #ifdef STRSTR
  1999. char *strstr();
  2000. #endif
  2001.  
  2002. #ifdef STRTOL
  2003. long strtol();
  2004. #endif
  2005.  
  2006. char *Prompts[] =
  2007. {
  2008.    "Login: ",
  2009.    "Password: ",
  2010.    "Password: ",
  2011.    "Enter Your Password Again: ",
  2012.    "Enter your e-mail address (None): ",
  2013.    "#> ",
  2014.    "#> ",
  2015.    "Enter Dead Group: ",
  2016.    "#> ",
  2017.    "#> ",
  2018. };
  2019.  
  2020.  
  2021. initparser()
  2022. {
  2023.    loggedon = 0;
  2024.    repeatpass = 0;
  2025.    repeatlogin = 0;
  2026.    verbosetog = 0;
  2027. }
  2028.  
  2029.  
  2030. DoState(s)
  2031. char *s;
  2032. {
  2033.    if (strncmp(s, Prompts[LOGON], strlen(Prompts[LOGON])) == 0)
  2034.       return LOGON;
  2035.    if (strncmp(s, "1 1", 3) == 0)
  2036.       return PASSWORD;
  2037.    if (strncmp(s, "1 0", 3) == 0)
  2038.       return LOGON;
  2039.    if (strncmp(s, Prompts[PASSWORD], strlen(Prompts[PASSWORD])) == 0)
  2040.       return PASSWORD;
  2041.    if (strncmp(s, Prompts[PASSWD_NEW], strlen(Prompts[PASSWD_NEW])) == 0)
  2042.       return PASSWD_NEW;
  2043.    if (strncmp(s, Prompts[PASSWD_CONFIRM],
  2044.            strlen(Prompts[PASSWD_CONFIRM])) == 0)
  2045.       return PASSWD_CONFIRM;
  2046.    if (strncmp(s, Prompts[WAITING], strlen(Prompts[WAITING])) == 0)
  2047.       return WAITING;
  2048.    if (!strncmp(s, "Too many players, sorry", 23) ||
  2049.        !strncmp(s, "Sorry, the server is full", 24))
  2050.       return TOOMANY;
  2051.    return -1;
  2052. }
  2053.  
  2054. static long appending = 0;
  2055.  
  2056. int getmessage(mess, checkstdin)
  2057. message *mess;
  2058. int checkstdin;
  2059. {
  2060.    char mesg[2000];
  2061.    int ret;
  2062.    char *textpart;
  2063.  
  2064.    ret = pollserver(mesg, checkstdin);
  2065.    if (ret <= 0)
  2066.       return ret;
  2067.    switch (DoState(mesg)) {
  2068.       case PASSWD_NEW:
  2069.       case PASSWD_CONFIRM:
  2070.       case PASSWORD:
  2071.      sendstr(getpassword(repeatpass++));
  2072.      break;
  2073.       case WAITING:
  2074.      sendstr("toggle client true\n");
  2075.      mess->id = ONSERVER;
  2076.      loggedon = 1;
  2077.      return 1;
  2078.       case TOOMANY:
  2079.      mess->id = TOOMANY;
  2080.      return 1;
  2081.       case LOGON:
  2082.      {
  2083.         int needlogin;
  2084.         needlogin = 1;
  2085.         do {
  2086.            if (needlogin == 1) {
  2087.           sendstr(getloginname(repeatlogin++));
  2088.           needlogin = -1;
  2089.            }
  2090.            ret = pollserver(mesg, 0);
  2091.            if (ret < 0)
  2092.           return ret;
  2093.            if (!strncmp(mesg, "Password:", 9) || (!strncmp(mesg, "1 1", 3)))
  2094.           needlogin = 0;
  2095.            else if (!strncmp(mesg, "Sorry", 5)) {
  2096.           puts(mesg);
  2097.           if (!strncmp(mesg, "Sorry, the server is full", 24)) {
  2098.              mess->id = TOOMANY;
  2099.              return 1;
  2100.           }
  2101.           return 0;
  2102.            } else if (strlen(mesg) > 2 && strncmp(mesg, "Login", 5))
  2103.           puts(mesg);
  2104.         } while (needlogin);
  2105.         sendstr(getpassword(repeatpass++));
  2106.         do {
  2107.            ret = pollserver(mesg, 0);
  2108.            if (ret < 0)
  2109.           return ret;
  2110.            if (!strncmp(mesg, "Enter", 5))
  2111.           sendstr(getpassword(repeatpass++));
  2112.            if (!strncmp(mesg, "9 File", 6))
  2113.           needlogin = -1;
  2114.            if (!strncmp(mesg, "To get", 6))
  2115.           needlogin = 1;
  2116.            if (!strncmp(mesg, "#>", 2)) {
  2117.           sendstr("toggle client true\n");
  2118.           mess->id = ONSERVER;
  2119.           loggedon = 1;
  2120.           return 1;
  2121.            }
  2122.            if (strstr(mesg, "Invalid") || strstr(mesg, "your name")
  2123.          || strstr(mesg, "Too few") || strstr(mesg, "do not match")) {
  2124.           if (*mesg == '5')
  2125.              puts(mesg + 2);
  2126.           else
  2127.              puts(mesg);
  2128.           needlogin = 1;
  2129.            }
  2130.         } while (!needlogin);
  2131.         if (needlogin > 0)
  2132.            break;
  2133.      }            /* intentional fall through occurs here */
  2134.      loggedon = 1;
  2135.       default:
  2136.      mess->id = strtol(mesg, &textpart, 10);
  2137.      if (!loggedon && !mess->id) {
  2138.         mess->id = INTRO;
  2139.         strcpy(mess->text, mesg);
  2140.         return 1;
  2141.      }
  2142.      textpart++;
  2143.      if (mess->id == 2 && (strstr(textpart, "Game")
  2144.                    || strstr(textpart, "min")))
  2145.         mess->id = TIMEREP;
  2146.      if (appending == -1) {
  2147.         if (mess->id && !strncmp(textpart, "File", 4)) {
  2148.            appending = 0;
  2149.            if (mess->id == INFO &&
  2150.            !strncmp(mess->text, "~~~~~~~~~~~~~~~~~~~~~", 21))
  2151.           mess->id = QUITMESG;
  2152.            return 1;
  2153.         }
  2154.         if (strlen(mess->text)) {
  2155.            strcat(mess->text, "\n");
  2156.            mess->lines++;
  2157.         } {
  2158.            int len;
  2159.            char *pt;
  2160.            len = strlen(mesg);
  2161.            pt = mesg;
  2162.            while (len > 0) {
  2163.           strncat(mess->text, pt, 79);
  2164.           len -= 79;
  2165.           pt += 79;
  2166.           if (len > 0) {
  2167.              mess->lines++;
  2168.              strcat(mess->text, "\n");
  2169.           }
  2170.            }
  2171.         }
  2172.         return 0;
  2173.      }
  2174.      if (mess->id == PROMPT) {
  2175.             if (!verbosetog) 
  2176.            sendstr("toggle verbose false\n");
  2177.         if (*textpart == '5' && !loggedon)
  2178.            loggedon = 1;
  2179.         if (appending == MOVE && mess->movecount == 0 &&
  2180.         atoi(textpart) == 6 /* TEACHING */ ) {
  2181.            mess->id = MATCH;
  2182.            return 1;
  2183.         }
  2184.         if (appending) {
  2185.            mess->id = appending;
  2186.  
  2187.            appending = 0;
  2188.            return 1;
  2189.         }
  2190.         mess->prompttype = atoi(textpart);
  2191.      }
  2192.      if (!strcmp(textpart, "File")) {
  2193.         appending = -1;
  2194.         strcpy(mess->text, "");
  2195.         mess->lines = 1;
  2196.         return 0;
  2197.      }
  2198.      if (mess->id == BEEP) {
  2199.         mess->beep = (*textpart == 7);
  2200.      }
  2201.      if (mess->id == KIBITZ) {
  2202.         if (parsekibitz(textpart, mess))
  2203.            return 0;
  2204.      }
  2205.      if (mess->id == UNDO)
  2206.         if (ret = parseundo(textpart, &(mess->gamenum))) {
  2207.            if (ret < 0)
  2208.           return ret;
  2209.            return 0;
  2210.         }
  2211.      if (mess->id == SCORE) {
  2212.         sscanf(textpart, "%[^ ] (W:%*c):%f to %[^ ] (B:%*c):%f",
  2213.            mess->white, &(mess->wscore), mess->black, &(mess->bscore));
  2214.         return 1;
  2215.      }
  2216.      if (mess->id == TRANSLATE) {
  2217.         if (appending) {
  2218.            strcat(mess->text, "\n");
  2219.            strcat(mess->text, textpart);
  2220.            mess->lines++;
  2221.         } else {
  2222.            strcpy(mess->text, textpart);
  2223.            mess->lines = 1;
  2224.         }
  2225.         appending = TRANSLATE;
  2226.         return 0;
  2227.      }
  2228.      if (mess->id == MOVE) {
  2229.         appending = MOVE;
  2230.         parsemove(textpart, mess);
  2231.         return 0;
  2232.      }
  2233.      if (mess->id == WHO)
  2234.         return parsewho(mess, textpart);
  2235.      if (mess->id == GAMES) {
  2236.         appending = GAMES;
  2237.         parsegame(mess, textpart);
  2238.         return 0;
  2239.      }
  2240.      if (mess->id == STATUS)
  2241.         return parsestatus(mess, textpart);
  2242.      strcpy(mess->text, textpart);
  2243.      mess->lines = 1;
  2244.          if (mess->id == SHOUT) 
  2245.             return checkgame(textpart, mess);
  2246.      if (mess->id == ERROR &&
  2247.          !strcmp("Game not found.", textpart)) {
  2248.         mess->id = GAMES;
  2249.         mess->gamecount = 0;
  2250.         return 1;
  2251.      }
  2252.      if (mess->id == INFO)
  2253.         if (ret = parseinfo(textpart, mess))
  2254.            return ret;
  2255.      return 1;
  2256.    }
  2257.    return 0;
  2258.  
  2259. }
  2260.  
  2261. #ifdef STRTOL
  2262. long strtol(text, new, dum)
  2263. char *text;
  2264. char **new;
  2265. int dum;
  2266. {
  2267.    long retu;
  2268.    retu = atol(text);
  2269.    for (*new = text; *new && **new <= '9' && **new >= '0'; (*new)++);
  2270.    return retu;
  2271. }
  2272. #endif
  2273.  
  2274.  
  2275.  
  2276. #ifdef STRSTR
  2277. char *strstr(s1, s2)
  2278. char *s1, *s2;
  2279. {
  2280.    register char *temp;
  2281.    int len;
  2282.  
  2283.    temp = s1;
  2284.    len = strlen(s2);
  2285.    while (temp = strchr(temp, *s2)) {
  2286.       if (!strncmp(temp, s2, len))
  2287.      return temp;
  2288.       else
  2289.      temp++;
  2290.    }
  2291.    return NULL;
  2292. }
  2293. #endif
  2294.  
  2295.  
  2296.  
  2297. int parsestatus(mesg, s)
  2298. message *mesg;
  2299. char *s;
  2300. {
  2301.    int line, i;
  2302.    char wflag, bflag;
  2303.  
  2304.    if (1 == sscanf(s, " %d:", &line)) {
  2305.       mesg->boardsize = line + 1;
  2306.       for (i = 0, s += 4; *s; i++, s++)
  2307.      switch (*s) {
  2308.         case S_BLACK:
  2309.            mesg->board[line][i] = BLACK;
  2310.            break;
  2311.         case S_WHITE:
  2312.            mesg->board[line][i] = WHITE;
  2313.            break;
  2314.         case S_EMPTY:
  2315.         case S_HOSHI:
  2316.            mesg->board[line][i] = EMPTY;
  2317.            break;
  2318.         case S_WTERR:
  2319.            mesg->board[line][i] = WTERR;
  2320.            break;
  2321.         case S_BTERR:
  2322.            mesg->board[line][i] = BTERR;
  2323.            break;
  2324.         case S_DAME:
  2325.            mesg->board[line][i] = DAME;
  2326.            break;
  2327.      }
  2328.       if (i == line + 1)
  2329.      return 1;
  2330.    } else {
  2331.       if (!mesg->wnext) {
  2332.      sscanf(s, "%[^ ] %[^ ] %d %d %d %c %f %d",
  2333.         mesg->white, mesg->wrank, &(mesg->bcap), &(mesg->wtime),
  2334.         &(mesg->wbyo), &wflag, &(mesg->mykomi), &(mesg->hcap));
  2335.      if (wflag == 'F')
  2336.         mesg->wbyo = -1;
  2337.       } else {
  2338.      sscanf(s, "%[^ ] %[^ ] %d %d %d %c %f %d",
  2339.         mesg->black, mesg->brank, &(mesg->wcap), &(mesg->btime),
  2340.         &(mesg->bbyo), &bflag, &(mesg->mykomi), &(mesg->hcap));
  2341.      if (bflag == 'F')
  2342.         mesg->bbyo = -1;
  2343.       }
  2344.       mesg->wnext = !mesg->wnext;
  2345.    }
  2346.    return 0;
  2347. }
  2348.  
  2349. #define WHOLENGTH 34
  2350.  
  2351.  
  2352. int parsewho(mesg, str)
  2353. message *mesg;
  2354. char *str;
  2355. {
  2356.    if (!strncmp(str, " Info", 5)) {
  2357.       mesg->whocount = 0;
  2358.       strcpy(mesg->text, str);
  2359.       mesg->lines = 1;
  2360.       strcpy(mesg->whofirst, str);
  2361.    } else {
  2362.       strcat(mesg->text, "\n");
  2363.       strcat(mesg->text, str);
  2364.       mesg->lines++;
  2365.       if (strstr(str, "******")) {
  2366.      strcpy(mesg->wholast, str);
  2367.      return 1;
  2368.       } else {
  2369.      strncpy(mesg->who[mesg->whocount++], str, WHOLENGTH);
  2370.      if (strlen(str) > 40)
  2371.         strncpy(mesg->who[mesg->whocount++], str + 37, WHOLENGTH);
  2372.       }
  2373.    }
  2374.    return 0;
  2375. }
  2376.  
  2377.  
  2378. parsegame(mesg, str)
  2379. message *mesg;
  2380. char *str;
  2381. {
  2382.    int fieldcount;
  2383.    char *br, *wr, blackrank[10], whiterank[10];
  2384.    if (str[1] == '#') {
  2385.       mesg->gamecount = 0;
  2386.       strcpy(mesg->text, str);
  2387.       strcpy(mesg->gamefirst, str);
  2388.       mesg->lines = 1;
  2389.    } else {
  2390.       strcpy(mesg->gamelist[mesg->gamecount].gametext, str);
  2391.       strcat(mesg->gamelist[mesg->gamecount].gametext, "\n");
  2392.       strcat(mesg->text, "\n");
  2393.       strcat(mesg->text, str);
  2394.       mesg->lines++;
  2395.  
  2396.       /* hacked for systems that don't like %[^]] */
  2397.       for (br = str; *br; br++)
  2398.      if (*br == ']')
  2399.         *br = '!';
  2400.       fieldcount = sscanf(str, "[%3d!%12s [%[^!]! vs.%12s [%[^!]! (%3d %d %d %f %d) ( %d)\n",
  2401.               &(mesg->gamelist[mesg->gamecount].gnum),
  2402.               mesg->gamelist[mesg->gamecount].white,
  2403.               whiterank,
  2404.               mesg->gamelist[mesg->gamecount].black,
  2405.               blackrank,
  2406.               &(mesg->gamelist[mesg->gamecount].mnum),
  2407.               &(mesg->gamelist[mesg->gamecount].bsize),
  2408.               &(mesg->gamelist[mesg->gamecount].hcap),
  2409.               &(mesg->gamelist[mesg->gamecount].komi),
  2410.               &(mesg->gamelist[mesg->gamecount].byo),
  2411.               &(mesg->gamelist[mesg->gamecount].obcount));
  2412.       br = blackrank;
  2413.       wr = whiterank;
  2414.       if (*br == ' ')
  2415.      br++;
  2416.       if (*wr == ' ')
  2417.      wr++;
  2418.       strcpy(mesg->gamelist[mesg->gamecount].wrank, wr);
  2419.       strcpy(mesg->gamelist[mesg->gamecount].brank, br);
  2420.       if (fieldcount == 11)
  2421.      (mesg->gamecount)++;
  2422.    }
  2423. }
  2424.  
  2425.  
  2426. int parseinfo(s, mess)
  2427. char *s;
  2428. message *mess;
  2429. {
  2430.    int ret;
  2431.    extern int boardsize;
  2432.    int row;
  2433.    char col;
  2434.    char text[100];
  2435.  
  2436.    if (checkgame(s, mess)) { mess->id = ENDGAMEINFO;return 0;}
  2437.    if (!strcmp(s, "Set verbose to be False.")) {
  2438.       mess->id = 0;
  2439.       verbosetog = 1;
  2440.       return 0;
  2441.    }
  2442.    if (!strcmp(s, "Set verbose to be True.")) {
  2443.       mess->id = 0;
  2444.       verbosetog = 0;
  2445.       return 0;
  2446.    }
  2447.    if (1 == sscanf(s, "Set the komi to %f.", &(mess->mykomi))) {
  2448.       mess->id = CHKOMI;
  2449.       return 0;
  2450.    }
  2451.    if (2 == sscanf(s, "Match [%dx%d]", &ret, &ret))
  2452.       return 0;
  2453.    if (1 == sscanf(s, "Match [%d]", &(mess->gamenum))) {
  2454.       mess->id = MATCH;
  2455.       return 0;
  2456.    }
  2457.    if (1 == sscanf(s, "Creating match [%d]", &(mess->gamenum))) {
  2458.       mess->id = MATCH;
  2459.       return 0;
  2460.    }
  2461.    if (2 == sscanf(s, "Removing @ %c%d", &col, &row)) {
  2462.  
  2463.       if (col > 'I')
  2464.      col--;
  2465.       mess->x = col - 'A';
  2466.       mess->y = boardsize - row;
  2467.       mess->id = REMOVE;
  2468.       return 0;
  2469.    }
  2470.    if (!strcmp(s, "Type 'done' when finished")) {
  2471.       mess->id = STARTSCORE;
  2472.       return 0;
  2473.    }
  2474.    if (!strncmp(s, "Board is restored", 17)) {
  2475.       mess->id = SCOREUNDO;
  2476.       return 0;
  2477.    }
  2478.    if (strstr(s, "has restored your old game.")) {
  2479.       char eat = 3, match = 0;
  2480.       mess->id = LOAD;
  2481.       for (; eat; eat--) {
  2482.      ret = pollserver(text, 0);
  2483.      if (ret < 0)
  2484.         return ret;
  2485.      if (!match)
  2486.         match = sscanf(text, "%*d Game %d: %*[^(](%d %d %d) vs %*[^(](%d %d %d)",
  2487.                &(mess->gamenum), &(mess->bcap), &(mess->btime),
  2488.            &(mess->bbyo), &(mess->wcap), &(mess->wtime), &(mess->wbyo)
  2489.            );
  2490.       }
  2491.       return 0;
  2492.    }
  2493.    return 0;
  2494. }
  2495.  
  2496.  
  2497. int parseundo(s, gamenum)
  2498. char *s;
  2499. int *gamenum;
  2500. {
  2501.    char mes[2000];
  2502.    int count;
  2503.    int bogus2, ret;
  2504.    char bogus1;
  2505.    count = sscanf(s, "%*[^ ] undid the last move (%c%d).", &bogus1, &bogus2);
  2506.    if (count == 2) {
  2507.       ret = pollserver(mes, 0);
  2508.       if (ret < 0)
  2509.      return ret;
  2510.       ret = pollserver(mes, 0);
  2511.       if (ret < 0)
  2512.      return ret;
  2513.       sscanf(mes, "%*d Game %d", gamenum);
  2514.       ret = pollserver(mes, 0);
  2515.       if (ret < 0)
  2516.      return ret;
  2517.       return 0;
  2518.    }
  2519.    if (1 == sscanf(s, "%*[^ ] undid the last move (Handicap %d).", &bogus2))
  2520.       return 0;
  2521.    count = sscanf(s, "Undo in game %d", gamenum);
  2522.    if (count != 1)
  2523.       return 1;            /* extra line */
  2524.    return 0;
  2525. }
  2526.  
  2527.  
  2528. int checkgame(s, mess)
  2529. char *s;
  2530. message *mess;
  2531.    if (!strncmp(s,"{Game ",6) && (strstr(s,"resigns.") ||  
  2532.      strstr(s,"forfeits on time.") || strstr(s, "adjourned."))){
  2533.  
  2534.      mess->id = ENDGAME;
  2535.      sscanf(s, "{Game %d", &(mess->gamenum));
  2536.      return 1;
  2537.    } 
  2538.    return 0;
  2539. }
  2540.      
  2541.  
  2542. int parsekibitz(s, mess)
  2543. char *s;
  2544. message *mess;
  2545. {
  2546.    if (1 == sscanf(s, "Kibitz %[^:]", mess->kibitzer))
  2547.       return 1;
  2548.    while (*s == ' ')
  2549.       s++;
  2550.    strcpy(mess->kibitz, s);
  2551.    return 0;
  2552.  
  2553. }
  2554.  
  2555.  
  2556. parsemove(s, mess)
  2557. char *s;
  2558. message *mess;
  2559. {
  2560.    int mc, y, mv;
  2561.    char c, col;
  2562.    extern int boardsize;
  2563.  
  2564.    if (!strncmp(s, "Game ", 5)) {
  2565.       sscanf(s, "Game %d: %*[^(](%d %d %d) vs %*[^(](%d %d %d)",
  2566.          &(mess->gamenum), &(mess->wcap), &(mess->wtime),
  2567.          &(mess->wbyo), &(mess->bcap),
  2568.          &(mess->btime), &(mess->bbyo));
  2569.       mess->movecount = 0;
  2570.       return;
  2571.    }
  2572.    mc = sscanf(s, "%3d(%c): %c%d", &mv, &c, &col, &y);
  2573.    if (mc == 3) {
  2574.       if (3 == sscanf(s, "%3d(%c): Handicap %d", &mv, &c, &mc)) {
  2575.      mess->moves[mess->movecount].x = mess->moves[mess->movecount].y = mc + 100;
  2576.      mess->moves[mess->movecount].color = c == 'W' ? 2 : 1;
  2577.      mess->moves[mess->movecount].movenum = mv + 1;
  2578.      mess->movecount++;
  2579.      return;
  2580.       }
  2581.       if (2 == sscanf(s, "%3d(%c): Pass", &mv, &c)) {
  2582.      mess->moves[mess->movecount].x = mess->moves[mess->movecount].y = 99;
  2583.      mess->moves[mess->movecount].color = c == 'W' ? 2 : 1;
  2584.      mess->moves[mess->movecount].movenum = mv + 1;
  2585.      mess->movecount++;
  2586.      return;
  2587.       }
  2588.    }
  2589.    if (col > 'I')
  2590.       col--;
  2591.    mess->moves[mess->movecount].x = col - 'A';
  2592.    mess->moves[mess->movecount].y = boardsize - y;
  2593.    mess->moves[mess->movecount].color = c == 'W' ? 2 : 1;
  2594.    mess->moves[mess->movecount].movenum = mv + 1;
  2595.    mess->movecount++;
  2596. }
  2597.  
  2598.  
  2599. int doneline(inbuf, inptr)
  2600. char *inbuf;
  2601. int inptr;
  2602. {
  2603.    return !loggedon &&
  2604.       (inptr > 0 && inbuf[inptr - 1] == ' ') &&
  2605.       ((inptr > 1 && inbuf[inptr - 2] == ':') ||
  2606.        (inptr > 2 && inbuf[inptr - 2] == '>' && inbuf[inptr - 3] == '#'));
  2607. }
  2608. SHAR_EOF
  2609. fi
  2610. if test -f 'ascii.c'
  2611. then
  2612.     echo shar: "will not over-write existing file 'ascii.c'"
  2613. else
  2614. cat << \SHAR_EOF > 'ascii.c'
  2615.  
  2616. #include <curses.h>
  2617.  
  2618. #define piece char
  2619.  
  2620. #define TOP 2
  2621. #define LEFT 3
  2622. #define RIGHT 79
  2623. #define min(a,b) (((a)<(b))?(a):(b))
  2624. #define TITLEX 6
  2625. #define HIGHLIGHT 23
  2626.  
  2627. #define   CHAR_NOTHING 0
  2628. #define   CHAR_BLACK 1
  2629. #define   CHAR_WHITE 2
  2630. #define   CHAR_DAME 3
  2631. #define   CHAR_BLACKTERR 4
  2632. #define   CHAR_WHITETERR 5
  2633. #define   CHAR_HANDICAP 6
  2634. #define   CHAR_VERT 7
  2635. #define   ASC_NUMCHARS 8
  2636.  
  2637.  
  2638. WINDOW *boardwin, *serverwin, *iowin;
  2639. char xAxisChars[] = "ABCDEFGHJKLMNOPQRST";
  2640. int inverseFlag = 1;
  2641. int inverseBorder = 0;
  2642. int lastwin = 1;
  2643. int boardsize = -1;
  2644. char chars[] = ".#O?+-+ ";
  2645. int servecols = -1;
  2646. static int init = 0;
  2647. int endw = -1, endb = -1;
  2648. int reinit = 0;
  2649. int doedgemarkers = 0;
  2650. int dopiecemarkers = 1;
  2651.  
  2652.  
  2653. setedgemark(mark)
  2654. int mark;
  2655. {
  2656.    doedgemarkers = mark;
  2657. }
  2658.  
  2659. setpiecemark(mark)
  2660. int mark;
  2661. {
  2662.    dopiecemarkers = mark;
  2663. }
  2664.  
  2665. setinverse(inv)
  2666. int inv;
  2667. {
  2668.    inverseFlag = inv;
  2669. }
  2670.  
  2671. setinverseborder(inv)
  2672. int inv;
  2673. {
  2674.    inverseBorder = inv;
  2675. }
  2676.  
  2677. setborder(ch)
  2678. char ch;
  2679. {
  2680.    chars[CHAR_VERT] = ch;
  2681. }
  2682.  
  2683. setchars(s)
  2684. char *s;
  2685. {
  2686.    int i;
  2687.    for (i = 0; i <= min(CHAR_VERT, strlen(s) - 1); i++)
  2688.       chars[i] = s[i];
  2689. }
  2690.  
  2691.  
  2692. serverrefresh()
  2693. {
  2694.    if (lastwin)
  2695.       wrefresh(iowin);
  2696.    else
  2697.       wrefresh(serverwin);
  2698. }
  2699.  
  2700. boardrefresh()
  2701. {
  2702.    wrefresh(boardwin);
  2703. }
  2704.  
  2705. void initAscii()
  2706. {
  2707.    if (!init) {
  2708.       init = 1;
  2709.       initscr();
  2710.       noecho();
  2711.       crmode();
  2712.    }
  2713. }
  2714.  
  2715. suspend()
  2716. {
  2717.    move(23, 0);
  2718.    refresh();
  2719.    echo();
  2720.    nocrmode();
  2721. }
  2722.  
  2723.  
  2724.  
  2725. redraw()
  2726. {
  2727.    clearok(stdscr, TRUE);
  2728.    refresh();
  2729.    clearok(stdscr, FALSE);
  2730. }
  2731.  
  2732.  
  2733. unsuspend()
  2734. {
  2735.    noecho();
  2736.    crmode();
  2737.    redraw();
  2738. }
  2739.  
  2740.  
  2741. displaygamenumber(n)
  2742. int n;
  2743. {
  2744.    move(0, 0);
  2745.    if (n >= 0)
  2746.       printw("%3d", n);
  2747.    else if (n == -1)
  2748.       printw("-- ");
  2749.    else
  2750.       printw("sta");
  2751.    refresh();
  2752. }
  2753.  
  2754. boardtitle(bs, ws)
  2755. char *bs, *ws;
  2756. {
  2757.    int i;
  2758.    move(0, TITLEX);
  2759.    for (i = 0; i < 35; i++)
  2760.       addch(' ');
  2761.    move(1, TITLEX);
  2762.    for (i = 0; i < 35; i++)
  2763.       addch(' ');
  2764.    if (strlen(bs)) {
  2765.       move(0, TITLEX);
  2766.       printw("Black: %s", bs);
  2767.       endb = TITLEX + 8 + strlen(bs);
  2768.       move(1, TITLEX);
  2769.       printw("White: %s", ws);
  2770.       endw = TITLEX + 8 + strlen(ws);
  2771.    }
  2772.    refresh();
  2773. }
  2774.  
  2775. static void sbinverse()
  2776. {
  2777.    if (inverseBorder)
  2778.       wstandout(boardwin);
  2779. }
  2780.  
  2781. static void set_inverse()
  2782. {
  2783.    if (inverseFlag)
  2784.       wstandout(boardwin);
  2785. }
  2786.  
  2787. static void unset_inverse()
  2788. {
  2789.    wstandend(boardwin);
  2790. }
  2791.  
  2792.  
  2793. setcursor(x, y)
  2794. int x, y;
  2795. {
  2796.    wmove(boardwin, TOP + y, LEFT + 2 * x);
  2797.    wrefresh(boardwin);
  2798. }
  2799.  
  2800.  
  2801. void drawPiece(i, j, c)
  2802. int i, j;
  2803. char c;
  2804. {
  2805.    wmove(boardwin, TOP + j, LEFT + 2 * i);
  2806.    set_inverse();
  2807.    waddch(boardwin, c);
  2808.    unset_inverse();
  2809. }
  2810.  
  2811.  
  2812. void deleteBoardAscii()
  2813. {
  2814.    delwin(boardwin);
  2815.    delwin(serverwin);
  2816.    delwin(iowin);
  2817. }
  2818.  
  2819.  
  2820. void endAscii()
  2821. {
  2822.    init = 0;
  2823.    deleteBoardAscii();
  2824.    boardsize = -1;
  2825.    clear();
  2826.    refresh();
  2827.    echo();
  2828.    nocrmode();
  2829.    endwin();
  2830. }
  2831.  
  2832.  
  2833. char boardPiece(x, y, boardsize)
  2834. int x, y, boardsize;
  2835. {
  2836.    return
  2837.  
  2838.       (((boardsize == 19 && x == 9) || (boardsize >= 10 &&
  2839.                     (x == 3 || x == boardsize - 4))
  2840.     || (boardsize > 6 && boardsize < 10 &&
  2841.         (x == 2 || x == boardsize - 3))) &&
  2842.        ((boardsize == 19 && y == 9) ||
  2843.     (boardsize >= 10 && (y == 3 || y == boardsize - 4))
  2844.     || (boardsize > 6 && boardsize < 10 &&
  2845.         (y == 2 || y == boardsize - 3))))
  2846.       ? chars[(int) CHAR_HANDICAP] : chars[(int) CHAR_NOTHING];
  2847. }
  2848.  
  2849.  
  2850.  
  2851. drawOneStone(i, j, t)
  2852. int i, j;
  2853. piece t;
  2854. {
  2855.    if (t == 0)
  2856.       drawPiece(i, j, boardPiece(i, j, boardsize));
  2857.    else
  2858.       drawPiece(i, j, chars[t]);
  2859.    wrefresh(boardwin);
  2860. }
  2861.  
  2862. drawStone(i, j, t)
  2863. int i, j;
  2864. piece t;
  2865. {
  2866.    if (t == 0)
  2867.       drawPiece(i, j, boardPiece(i, j, boardsize));
  2868.    else
  2869.       drawPiece(i, j, chars[t]);
  2870. }
  2871.  
  2872.  
  2873. unmarkascii(i, j)
  2874. int i, j;
  2875. {
  2876.    if (!init)
  2877.       return;
  2878.    if (i >= 0 && i <= 19) {
  2879.       set_inverse();
  2880.       if (dopiecemarkers) {
  2881.      wmove(boardwin, TOP + j, LEFT + 2 * i - 1);
  2882.      waddch(boardwin, ' ');
  2883.      wmove(boardwin, TOP + j, LEFT + 2 * i + 1);
  2884.      waddch(boardwin, ' ');
  2885.       }
  2886.       if (doedgemarkers) {
  2887.      wmove(boardwin, TOP + j, LEFT - 1);
  2888.      waddch(boardwin, chars[CHAR_VERT]);
  2889.      wmove(boardwin, TOP + j, LEFT + boardsize * 2 - 1);
  2890.      waddch(boardwin, chars[CHAR_VERT]);
  2891.      unset_inverse();
  2892.      sbinverse();
  2893.      wmove(boardwin, TOP - 1, LEFT + i * 2);
  2894.      waddch(boardwin, xAxisChars[i]);
  2895.      wmove(boardwin, TOP + boardsize, LEFT + i * 2);
  2896.      waddch(boardwin, xAxisChars[i]);
  2897.       }
  2898.       unset_inverse();
  2899.    }
  2900. }
  2901.  
  2902. unhighlight(i, j)
  2903. int i, j;
  2904. {
  2905.    int k;
  2906.    if (!init)
  2907.       return;
  2908.    move(HIGHLIGHT, 0);
  2909.    for (k = 1; k < 80 - servecols; k++)
  2910.       addch(' ');
  2911.    move(0, TITLEX - 2);
  2912.    printw("  ");
  2913.    move(1, TITLEX - 2);
  2914.    printw("  ");
  2915.    unmarkascii(i, j);
  2916. }
  2917.  
  2918. static char *who[] =
  2919. {"Black", "White"};
  2920.  
  2921. showhcap(hcap)
  2922. int hcap;
  2923. {
  2924.    if (!init)
  2925.       return;
  2926.    move(0, LEFT + 19 * 2 + 1);
  2927.    if (hcap)
  2928.       printw("%d", hcap);
  2929.    else
  2930.       addch(' ');
  2931.    refresh();
  2932. }
  2933.  
  2934. showkomi(komi)
  2935. float komi;
  2936. {
  2937.    if (!init)
  2938.       return;
  2939.    move(1, LEFT + 19 * 2 - 1);
  2940.    printw("%1.1f", komi);
  2941.    refresh();
  2942. }
  2943.  
  2944. highlight(i, j, num, t, btime, bbyo, wtime, wbyo)
  2945. int i, j;
  2946. piece t;
  2947. int btime, bbyo, wtime, wbyo;
  2948. {
  2949.    int k;
  2950.    if (btime != -1) {
  2951.       move(0, endb);
  2952.       if (btime < 0)
  2953.      btime = 0;
  2954.       if (wtime < 0)
  2955.      wtime = 0;
  2956.       printw("%d:%02d", btime / 60, btime % 60);
  2957.       if (bbyo != -1)
  2958.      printw(", %d", bbyo);
  2959.       addstr("   ");
  2960.       move(1, endw);
  2961.       printw("%d:%02d", wtime / 60, wtime % 60);
  2962.       if (wbyo != -1)
  2963.      printw(", %d", wbyo);
  2964.       addstr("   ");
  2965.    }
  2966.    if (t >= 0) {
  2967.       move(t == 1 ? 1 : 0, TITLEX - 2);
  2968.       printw("->");
  2969.    }
  2970.    move(HIGHLIGHT, 0);
  2971.    for (k = 1; k < 80 - servecols; k++)
  2972.       addch(' ');
  2973.    if (i == 99) {
  2974.       move(HIGHLIGHT, 0);
  2975.       printw("%s #%d Pass", who[t - 1], num);
  2976.    } else if (i < 100 && num) {
  2977.       move(HIGHLIGHT, 0);
  2978.       printw("%s #%d at %c%d", who[t - 1], num, i + 'A' +
  2979.          (i + 'A' >= 'I' ? 1 : 0), boardsize - j);
  2980.       set_inverse();
  2981.       if (dopiecemarkers) {
  2982.      wmove(boardwin, TOP + j, LEFT + 2 * i - 1);
  2983.      waddch(boardwin, '>');
  2984.      wmove(boardwin, TOP + j, LEFT + 2 * i + 1);
  2985.      waddch(boardwin, '<');
  2986.       }
  2987.       if (doedgemarkers) {
  2988.      wmove(boardwin, TOP + j, LEFT - 1);
  2989.      waddch(boardwin, '>');
  2990.      wmove(boardwin, TOP + j, LEFT + boardsize * 2 - 1);
  2991.      waddch(boardwin, '<');
  2992.      unset_inverse();
  2993.      sbinverse();
  2994.      wmove(boardwin, TOP - 1, LEFT + i * 2);
  2995.      waddch(boardwin, '!');
  2996.      wmove(boardwin, TOP + boardsize, LEFT + i * 2);
  2997.      waddch(boardwin, '!');
  2998.       }
  2999.       unset_inverse();
  3000.    }
  3001. }
  3002.  
  3003.  
  3004.  
  3005. drawpris(pris)
  3006. int *pris;
  3007. {
  3008.    move(23, 22);
  3009.    printw("Captured %c: %d  %c: %d  ", chars[CHAR_BLACK], *pris,
  3010.       chars[CHAR_WHITE], pris[1]);
  3011.    refresh();
  3012. }
  3013.  
  3014.  
  3015.  
  3016. void initBoardAscii(size)
  3017. int size;
  3018. {
  3019.    int i, j;
  3020.    if (!reinit) {
  3021.       if (size == boardsize) {
  3022.      for (i = boardsize; i--;)
  3023.         for (j = boardsize; j--;)
  3024.            drawStone(i, j, 0);
  3025.      return;
  3026.       }
  3027.       if (boardsize != -1)
  3028.      deleteBoardAscii();
  3029.       boardsize = size;
  3030.       clear();
  3031.       boardwin = subwin(stdscr, boardsize + 4, boardsize * 2 - 1 + 6 + 2, 1, 0);
  3032.       servecols = COLS - 19 * 2 - 6 - 2;
  3033.       serverwin = subwin(stdscr, 22, servecols, 0, 19 * 2 - 1 + 6 + 2);
  3034.  
  3035.       iowin = subwin(stdscr, 2, servecols, 22, 19 * 2 - 1 + 6 + 2);
  3036.    }
  3037.    if (inverseFlag || reinit) {
  3038.       set_inverse();
  3039.       for (i = LEFT + 1; i < LEFT + boardsize * 2 - 2; i += 2)
  3040.      for (j = TOP; j < TOP + boardsize; j++)
  3041.         mvwaddch(boardwin, j, i, ' ');
  3042.       unset_inverse();
  3043.    }
  3044.    for (i = boardsize; i--;) {
  3045.       /* left */
  3046.       wmove(boardwin, TOP + i, LEFT - 3);
  3047.       sbinverse();
  3048.       wprintw(boardwin, "%2d", boardsize - i);
  3049.       unset_inverse();
  3050.       set_inverse();
  3051.       waddch(boardwin, chars[(int) CHAR_VERT]);
  3052.  
  3053.       /* right */
  3054.       wmove(boardwin, TOP + i, LEFT + boardsize * 2 - 1);
  3055.       waddch(boardwin, chars[(int) CHAR_VERT]);
  3056.       unset_inverse();
  3057.       sbinverse();
  3058.       wprintw(boardwin, "%2d", boardsize - i);
  3059.       unset_inverse();
  3060.       waddch(boardwin, chars[(int) CHAR_VERT]);
  3061.  
  3062.       /* top */
  3063.       wmove(boardwin, TOP - 1, LEFT + i * 2);
  3064.       sbinverse();
  3065.       waddch(boardwin, xAxisChars[i]);
  3066.       waddch(boardwin, ' ');
  3067.       unset_inverse();
  3068.       wmove(boardwin, TOP - 1, LEFT + i * 2 - 1);
  3069.       set_inverse();
  3070.  
  3071.       /* bottom */
  3072.       wmove(boardwin, TOP + boardsize, LEFT + i * 2 - 1);
  3073.       unset_inverse();
  3074.       wmove(boardwin, TOP + boardsize, LEFT + i * 2);
  3075.       sbinverse();
  3076.       waddch(boardwin, xAxisChars[i]);
  3077.       waddch(boardwin, ' ');
  3078.       unset_inverse();
  3079.       for (j = boardsize; j--;)
  3080.      drawStone(i, j, 0);
  3081.    }
  3082.  
  3083.    sbinverse();
  3084.    wmove(boardwin, TOP - 1, LEFT - 3);
  3085.    waddstr(boardwin, "   ");
  3086.    wmove(boardwin, TOP + boardsize, LEFT - 3);
  3087.    waddstr(boardwin, "   ");
  3088.    wmove(boardwin, TOP - 1, LEFT + 2 * boardsize);
  3089.    waddstr(boardwin, "  ");
  3090.    wmove(boardwin, TOP + boardsize, LEFT + 2 * boardsize);
  3091.    waddstr(boardwin, "  ");
  3092.    unset_inverse();
  3093.  
  3094.    wmove(boardwin, size / 2, size / 2);
  3095. }
  3096.  
  3097. reinitboardascii()
  3098. {
  3099.    reinit = 1;
  3100.    initBoardAscii(boardsize);
  3101.    reinit = 0;
  3102. }
  3103.  
  3104.  
  3105. clearserver()
  3106. {
  3107.    wclear(serverwin);
  3108.    wrefresh(serverwin);
  3109. }
  3110.  
  3111.  
  3112. addcharline(pos, ch)
  3113. int pos;
  3114. char ch;
  3115. {
  3116.    wmove(iowin, 1, pos);
  3117.    waddch(iowin, ch);
  3118.    wrefresh(iowin);
  3119.    lastwin = 1;
  3120. }
  3121.  
  3122.  
  3123. deletechar(pos)
  3124. int pos;
  3125. {
  3126.    wmove(iowin, 1, pos);
  3127.    waddch(iowin, ' ');
  3128.    wmove(iowin, 1, pos);
  3129.    wrefresh(iowin);
  3130.    lastwin = 1;
  3131. }
  3132.  
  3133.  
  3134. int linesize()
  3135. {
  3136.    return servecols - 1;
  3137. }
  3138.  
  3139. clrline()
  3140. {
  3141.    wmove(iowin, 1, 0);
  3142.    wclrtoeol(iowin);
  3143.    wrefresh(iowin);
  3144. }
  3145.  
  3146.  
  3147. addchar(ch)
  3148. char ch;
  3149. {
  3150.    int x, y, maxx, maxy;
  3151.    if (ch == '\r')
  3152.       return;
  3153.    waddch(serverwin, ch);
  3154.    maxy = serverwin->_maxy - 1;    /* 20 */
  3155.    maxx = serverwin->_maxx - 1;    /* servecols - 1; */
  3156.    getyx(serverwin, y, x);
  3157.    if ((x == maxx - 1 && y == maxy) || (ch == '\n' && y == maxy) ||
  3158.        y > maxy) {
  3159.       wmove(serverwin, 0, 0);
  3160.       wclrtoeol(serverwin);
  3161.    } else if (x == 0 && y <= maxy) {
  3162.       wclrtoeol(serverwin);
  3163.       wmove(serverwin, y + 1, 0);
  3164.       wclrtoeol(serverwin);
  3165.       wmove(serverwin, y, x);
  3166.    }
  3167.    wrefresh(serverwin);
  3168.    lastwin = 0;
  3169. }
  3170.  
  3171. showprefix(s)
  3172. char *s;
  3173. {
  3174.    wmove(iowin, 0, 0);
  3175.    wclrtoeol(iowin);
  3176.    if (strlen(s))
  3177.       wprintw(iowin, "Prefix: '%s'", s);
  3178.    wrefresh(iowin);
  3179. }
  3180.  
  3181.  
  3182. /* addstring(s) char *s; { char *p; for (p = s; *p; p++) addchar(*p); } */
  3183.  
  3184.  
  3185. void addstring(s)
  3186. char *s;
  3187. {
  3188.    char *wordstart;
  3189.    char *curptr;
  3190.    int haveblank, linelen;
  3191.  
  3192.    curptr = wordstart = s;
  3193.    linelen = 0;
  3194.    while (*curptr) {
  3195.       while (*curptr && *curptr != ' ' && *curptr != '\n') {
  3196.      linelen++;
  3197.      curptr++;
  3198.       }
  3199.       if (*curptr) {
  3200.      haveblank = 1;
  3201.      linelen++;
  3202.      curptr++;
  3203.       } else
  3204.      haveblank = 0;
  3205.  
  3206.       if (linelen <= linesize()) {
  3207.      while (wordstart != curptr)
  3208.         addchar(*wordstart++);
  3209.      if (haveblank && *(curptr - 1) == '\n')
  3210.         linelen = 0;
  3211.       } else if (haveblank && (linelen - 1 <= linesize())) {
  3212.      while (wordstart != curptr - 1)
  3213.         addchar(*wordstart++);
  3214.      addchar('\n');
  3215.      wordstart++;
  3216.      linelen = 0;
  3217.       } else {
  3218.      if ((curptr - wordstart) > linesize()) {
  3219.         while ((curptr - wordstart) > linesize()) {
  3220.            int i;
  3221.            for (i = linesize(); i; i--)
  3222.           addchar(*wordstart++);
  3223.            addchar('\n');
  3224.         }
  3225.      } else
  3226.         addchar('\n');
  3227.  
  3228.      linelen = 0;
  3229.      while (wordstart != curptr) {
  3230.         addchar(*wordstart++);
  3231.         linelen++;
  3232.      }
  3233.  
  3234.       }
  3235.    }
  3236. }
  3237.  
  3238.  
  3239.  
  3240. bigmess(lines, intext)
  3241. int lines;
  3242. char *intext;
  3243. {
  3244.    WINDOW *savescr;
  3245.    char ch;
  3246.    int i, count;
  3247.    int rest;
  3248.    char *mynl, *localcopy, *text;
  3249.  
  3250.    text = localcopy = (char *) malloc(strlen(intext) + 1);
  3251.    strcpy(text, intext);
  3252.    mynl = "";
  3253.    if (lines > 22) {
  3254.       rest = lines;
  3255.       lines = 22;
  3256.    } else
  3257.       rest = 0;
  3258.    savescr = newwin(24, 80, 0, 0);
  3259.    overwrite(stdscr, savescr);
  3260.    do {
  3261.       if (rest > 0) {
  3262.      for (mynl = text, count = 22; count && *mynl; mynl++)
  3263.         if (*mynl == '\n')
  3264.            count--;
  3265.      *(mynl - 1) = 0;
  3266.      rest -= 22;
  3267.       }
  3268.       for (i = (24 - lines) / 2 - 1; i < (24 - lines) / 2 + lines + 1; i++) {
  3269.      move(i, 0);
  3270.      clrtoeol();
  3271.       }
  3272.       move((24 - lines) / 2, 0);
  3273.       addstr(text);
  3274.       refresh();
  3275.       while (read(0, &ch, 1) != 1);
  3276.       text = mynl;
  3277.    } while (rest > 0);
  3278.    overwrite(savescr, stdscr);
  3279.    refresh();
  3280.    delwin(savescr);
  3281.    free(localcopy);
  3282. }
  3283. SHAR_EOF
  3284. fi
  3285. if test -f 'board.c'
  3286. then
  3287.     echo shar: "will not over-write existing file 'board.c'"
  3288. else
  3289. cat << \SHAR_EOF > 'board.c'
  3290. #include "igc.h"
  3291.  
  3292. typedef char boardtype[19][19];
  3293. int prisoners[2];
  3294. int movenum, maxmove;
  3295.  
  3296. typedef struct {
  3297.    int x, y;
  3298.    char col;
  3299. }  movelist[500];
  3300.  
  3301. movelist moves;
  3302.  
  3303. boardtype board;
  3304.  
  3305. #define boolean char
  3306. #define false 0
  3307. #define true 1
  3308.  
  3309. static int boardsize = -1;
  3310.  
  3311. int lasti = -1, lastj = -1;
  3312.  
  3313.  
  3314. clearboard(b, pris)
  3315. boardtype b;
  3316. int *pris;
  3317. {
  3318.    int i, j;
  3319.    pris[0] = pris[1] = 0;
  3320.    for (i = 0; i < boardsize; i++)
  3321.       for (j = 0; j < boardsize; j++)
  3322.      b[i][j] = EMPTY;
  3323. }
  3324.  
  3325.  
  3326. initboard(size)
  3327. int size;
  3328. {
  3329.    clearboard(board, prisoners);
  3330.    unhighlight(lasti, lastj);
  3331.    showhcap(0);
  3332.    initAscii();
  3333.    initBoardAscii(size);
  3334.    boardsize = size;
  3335.    maxmove = movenum = 0;
  3336. }
  3337.  
  3338.  
  3339. reinitboard(size)
  3340. int size;
  3341. {
  3342.    unhighlight(lasti, lastj);
  3343.    showhcap(0);
  3344.    clearboard(board, prisoners);
  3345.    initAscii();
  3346.    reinitboardascii();
  3347.    boardsize = size;
  3348. }
  3349.  
  3350. boolean inRange(i, j)
  3351. {
  3352.    return i >= 0 && i < boardsize && j >= 0 && j < boardsize;
  3353. }
  3354.  
  3355. boolean alive0(b, m, i, j, t)
  3356. boardtype b;
  3357. boardtype m;
  3358. int i, j;
  3359. piece t;
  3360. {
  3361.    piece pt;
  3362.  
  3363.    pt = b[i][j];
  3364.    if ((pt != EMPTY && pt != t) || m[i][j] != EMPTY)
  3365.       return 0;
  3366.    m[i][j] = (pt == t) ? (piece) 1 : (piece) 2;
  3367.    if (pt == EMPTY)
  3368.       return 1;
  3369.    return
  3370.       (j < boardsize - 1 && alive0(b, m, i, j + 1, t)) ||
  3371.       (i < boardsize - 1 && alive0(b, m, i + 1, j, t)) ||
  3372.       (i && alive0(b, m, i - 1, j, t)) ||
  3373.       (j && alive0(b, m, i, j - 1, t));
  3374. }
  3375.  
  3376. boolean alive(b, i, j)        /* Does group at i,j have liberties? */
  3377. boardtype b;
  3378. int i, j;
  3379. {
  3380.    boardtype m;
  3381.    int p[2];
  3382.  
  3383.    clearboard(m, p);
  3384.    return alive0(b, m, i, j, b[i][j]);
  3385. }
  3386.  
  3387. int removed;
  3388. int dontdraw = 0;
  3389.  
  3390. void removeStones0(b, pris, i, j, t)
  3391. boardtype b;
  3392. int *pris;
  3393. int i, j;
  3394. piece t;
  3395. {
  3396.    if (b[i][j] != t)
  3397.       return;
  3398.    b[i][j] = EMPTY;
  3399.    if (!dontdraw)
  3400.       drawStone(i, j, 0);
  3401.    removed = 1;
  3402.    pris[t - 1]++;
  3403.    if (j < boardsize - 1)
  3404.       removeStones0(b, pris, i, j + 1, t);
  3405.    if (i < boardsize - 1)
  3406.       removeStones0(b, pris, i + 1, j, t);
  3407.    if (i)
  3408.       removeStones0(b, pris, i - 1, j, t);
  3409.    if (j)
  3410.       removeStones0(b, pris, i, j - 1, t);
  3411. }
  3412.  
  3413.  
  3414.  
  3415. void removeStones(b, pris, i, j)
  3416. boardtype b;
  3417. int *pris;
  3418. int i, j;
  3419. {
  3420.    removed = 0;
  3421.    removeStones0(b, pris, i, j, b[i][j]);
  3422.    /* if (removed) boardrefresh(); */
  3423.  
  3424. }
  3425.  
  3426.  
  3427. void removeGroup(i, j)
  3428. int i, j;
  3429. {
  3430.    removeStones(board, prisoners, i, j);
  3431. }
  3432.  
  3433. boolean tryKill(b, pris, i, j, t)
  3434. boardtype b;
  3435. int *pris;
  3436. int i, j;
  3437. piece t;
  3438. {
  3439.    piece w;
  3440.    if (!inRange(i, j))
  3441.       return false;
  3442.    w = b[i][j];
  3443.    if (w != EMPTY && w != t && !alive(b, i, j)) {
  3444.       removeStones(b, pris, i, j);
  3445.       return true;
  3446.    }
  3447.    return false;
  3448. }
  3449.  
  3450. void placeStone(b, pris, i, j, t)
  3451. boardtype b;
  3452. int *pris;
  3453. int i, j;
  3454. piece t;
  3455. {
  3456.    if (inRange(i, j)) {
  3457.       b[i][j] = t;
  3458.       if (j)
  3459.      tryKill(b, pris, i, j - 1, t);
  3460.       if (j < boardsize - 1)
  3461.      tryKill(b, pris, i, j + 1, t);
  3462.       if (i)
  3463.      tryKill(b, pris, i - 1, j, t);
  3464.       if (i < boardsize - 1)
  3465.      tryKill(b, pris, i + 1, j, t);
  3466.    }
  3467. }
  3468.  
  3469.  
  3470.  
  3471.  
  3472. static highlighting = 1;
  3473.  
  3474. makemove(i, j, num, t, btime, bbyo, wtime, wbyo)
  3475. int i, j;
  3476. piece t;
  3477. int btime, bbyo, wtime, wbyo;
  3478. {
  3479.    if (movenum != maxmove) {
  3480.       construct(maxmove);
  3481.    }
  3482.    if (highlighting)
  3483.       unhighlight(lasti, lastj);
  3484.    if (num == 1 && i <= 19)
  3485.       showhcap(0);
  3486.    if (i > 100) {
  3487.       sethandicap(board, i - 100);
  3488.       showhcap(i - 100);
  3489.       moves[num].x = moves[num].y = i;
  3490.       moves[num].col = t;
  3491.       maxmove = movenum = num;
  3492.       if (highlighting)
  3493.      highlight(i, j, num, t, btime, bbyo, wtime, wbyo);
  3494.       return;
  3495.    }
  3496.    if (i == 99) {
  3497.       moves[num].x = moves[num].y = 99;
  3498.       moves[num].col = t;
  3499.       maxmove = movenum = num;
  3500.       if (highlighting) {
  3501.      highlight(i, j, num, t, btime, bbyo, wtime, wbyo);
  3502.      drawpris(prisoners);
  3503.       }
  3504.       return;
  3505.    }
  3506.    placeStone(board, prisoners, i, j, t);
  3507.    if (highlighting)
  3508.       highlight(i, j, num, t, btime, bbyo, wtime, wbyo);
  3509.    if (highlighting)
  3510.       drawpris(prisoners);
  3511.    if (highlighting)
  3512.       drawOneStone(i, j, t);
  3513.    else
  3514.       drawStone(i, j, t);
  3515.    lasti = i;
  3516.    lastj = j;
  3517.    moves[num].x = i;
  3518.    moves[num].y = j;
  3519.    moves[num].col = t;
  3520.    maxmove = movenum = num;
  3521. }
  3522.  
  3523.  
  3524. unmark()
  3525. {
  3526.    unmarkascii(lasti, lastj);
  3527. }
  3528.  
  3529.  
  3530. construct(mov)
  3531. int mov;
  3532. {
  3533.    int i, j;
  3534.    boardtype myboard;
  3535.    int mypris[2];
  3536.  
  3537.    if (mov > maxmove)
  3538.       mov = maxmove;
  3539.    if (mov < 1)
  3540.       mov = 1;
  3541.    clearboard(myboard, mypris);
  3542.    unhighlight(lasti, lastj);
  3543.    dontdraw = 1;
  3544.    for (i = 1; i <= mov; i++) {
  3545.       if (moves[i].x > 100)
  3546.      sethandicap(myboard, moves[i].x - 100);
  3547.       else if (moves[i].x != 99) {
  3548.      placeStone(myboard, mypris, moves[i].x, moves[i].y, moves[i].col);
  3549.      myboard[moves[i].x][moves[i].y] = moves[i].col;
  3550.       }
  3551.    }
  3552.    dontdraw = 0;
  3553.    for (i = 0; i < boardsize; i++)
  3554.       for (j = 0; j < boardsize; j++)
  3555.      if (board[i][j] != myboard[i][j]) {
  3556.         drawStone(i, j, myboard[i][j]);
  3557.         board[i][j] = myboard[i][j];
  3558.      }
  3559.    prisoners[0] = mypris[0];
  3560.    prisoners[1] = mypris[1];
  3561.    highlight(moves[mov].x, moves[mov].y, mov, moves[mov].col,
  3562.          -1, -1, -1, -1);
  3563.    lasti = moves[mov].x;
  3564.    lastj = moves[mov].y;
  3565.    drawpris(prisoners);
  3566.    movenum = mov;
  3567. }
  3568.  
  3569.  
  3570. int savemaxmove = 0, didsave = 0;
  3571.  
  3572.  
  3573. restoremaxmoves()
  3574. {
  3575.    didsave = 0;
  3576.    maxmove = savemaxmove;
  3577. }
  3578.  
  3579. savemaxmoves()
  3580. {
  3581.    if (!didsave) {
  3582.       didsave = 1;
  3583.       savemaxmove = maxmove;
  3584.    }
  3585. }
  3586.  
  3587.  
  3588. showboard(b)
  3589. boardtype b;
  3590. {
  3591.    int i, j;
  3592.    for (i = 0; i < boardsize; i++)
  3593.       for (j = 0; j < boardsize; j++)
  3594.      if (board[i][j] != b[i][j]) {
  3595.         drawStone(i, j, b[i][j]);
  3596.         board[i][j] = b[i][j];
  3597.      }
  3598.    boardrefresh();
  3599. }
  3600.  
  3601.  
  3602. undo()
  3603. {
  3604.    int i, j;
  3605.  
  3606.    maxmove--;
  3607.    if (maxmove)
  3608.       construct(maxmove);
  3609.    else {
  3610.       movenum = 0;
  3611.       unhighlight(lasti, lastj);
  3612.       for (i = 0; i < boardsize; i++)
  3613.      for (j = 0; j < boardsize; j++)
  3614.         if (board[i][j] != EMPTY) {
  3615.            drawStone(i, j, EMPTY);
  3616.            board[i][j] = EMPTY;
  3617.         }
  3618.    }
  3619. }
  3620.  
  3621.  
  3622. int forward(num)
  3623. int num;
  3624. {
  3625.    if (!maxmove)
  3626.       return 1;
  3627.    if (movenum < maxmove)
  3628.       construct(movenum + num);    /* construct() does bounds checking */
  3629.    return 0;
  3630. }
  3631.  
  3632.  
  3633. int backward(num)
  3634. int num;
  3635. {
  3636.    if (!maxmove)
  3637.       return 1;
  3638.    if (movenum > 1)
  3639.       construct(movenum - num);    /* construct() does bounds checking */
  3640.    return 0;
  3641. }
  3642.  
  3643.  
  3644. int beginninggame()
  3645. {
  3646.    if (!maxmove)
  3647.       return 1;
  3648.    construct(1);
  3649.    return 0;
  3650. }
  3651.  
  3652. int endgame()
  3653. {
  3654.    if (!maxmove)
  3655.       return 1;
  3656.    construct(maxmove);
  3657.    return 0;
  3658. }
  3659.  
  3660.  
  3661. int search(i, j)
  3662. int i, j;
  3663. {
  3664.    int k;
  3665.    k = maxmove;
  3666.    while (k > 0 && (moves[k].x != i || moves[k].y != j))
  3667.       k--;
  3668.    if (!k)
  3669.       return 1;
  3670.    construct(k);
  3671.    return 0;
  3672. }
  3673.  
  3674.  
  3675. sethighlight(h)
  3676. int h;
  3677. {
  3678.    highlighting = h;
  3679. }
  3680.  
  3681. #define TOP 0
  3682. #define MID 1
  3683. #define BOT 2
  3684. static int verts[3][26] =
  3685. {
  3686.    {0, 0, 0, 0, 0, 0, 0, 0, 0,
  3687.     2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 3, 0, 3, 0, 0, 0, 4},
  3688.    {0, 0, 0, 0, 0, 0, 0, 0, 0,
  3689.     4, 0, 0, 0, 6, 0, 0, 0, 0, 0, 9, 0, 10, 0, 0, 0, 12},
  3690.    {0, 0, 0, 0, 0, 0, 0, 0, 0,
  3691.     6, 0, 0, 0, 9, 0, 0, 0, 0, 0, 15, 0, 17, 0, 0, 0, 20},
  3692. };
  3693.  
  3694.  
  3695.  
  3696. sethandicap(board, hand)
  3697. boardtype board;
  3698. int hand;
  3699. {
  3700.    /* This is also used to set the handicap.  The 'handi' is the number of
  3701.     * things to set of piece 'p'. */
  3702.  
  3703.    int top, mid, bot;
  3704.    piece t;
  3705.  
  3706.    top = verts[TOP][boardsize];
  3707.    mid = verts[MID][boardsize];
  3708.    bot = verts[BOT][boardsize];
  3709.  
  3710.    /* All of these drop through, '5' checks for odd points. */
  3711.    t = 1;
  3712.    switch (hand) {
  3713.       case 9:            /* taken care of by handi == 5 */
  3714.       case 8:
  3715.      drawStone(mid, top, t);
  3716.      board[mid][top] = t;
  3717.      drawStone(mid, bot, t);
  3718.      board[mid][bot] = t;
  3719.       case 7:            /* taken care of by handi == 5 */
  3720.       case 6:
  3721.      drawStone(bot, mid, t);
  3722.      board[bot][mid] = t;
  3723.      drawStone(top, mid, t);
  3724.      board[top][mid] = t;
  3725.       case 5:
  3726.      if (hand & 0x1) {    /* odd points, test because of drop through */
  3727.         drawStone(mid, mid, t);
  3728.         board[mid][mid] = t;
  3729.      }
  3730.       case 4:
  3731.      drawStone(bot, bot, t);
  3732.      board[bot][bot] = t;
  3733.       case 3:
  3734.      drawStone(top, top, t);
  3735.      board[top][top] = t;
  3736.       case 2:
  3737.      drawStone(bot, top, t);
  3738.      board[bot][top] = t;
  3739.      drawStone(top, bot, t);
  3740.      board[top][bot] = t;
  3741.      break;
  3742.       default:
  3743.      break;
  3744.    }
  3745. }
  3746. SHAR_EOF
  3747. fi
  3748. if test -f 'numbers.h'
  3749. then
  3750.     echo shar: "will not over-write existing file 'numbers.h'"
  3751. else
  3752. cat << \SHAR_EOF > 'numbers.h'
  3753. typedef enum {
  3754.    UNKNOWN = 0,
  3755.    BEEP = 2,            /* \7 telnet          */
  3756.    BOARD = 3,            /* Board being drawn      */
  3757.    DOWN = 4,            /* The server is going down */
  3758.    ERROR = 5,            /* An error reported     */
  3759.    FIL = 6,            /* File being sent     */
  3760.    GAMES = 7,            /* Games listing     */
  3761.    HELP = 8,            /* Help file         */
  3762.    INFO = 9,            /* Generic info         */
  3763.    LAST = 10,            /* Last command         */
  3764.    KIBITZ = 11,            /* Kibitz strings     */
  3765.    LOAD = 12,            /* Loading a game     */
  3766.    LOOK = 13,            /* Look          */
  3767.    MESSAGE = 14,        /* Message lising     */
  3768.    MOVE = 15,            /* Move #:(B) A1     */
  3769.    OBSERVE = 16,        /* Observe report     */
  3770.    PROMPT = 1,            /* A Prompt (never)     */
  3771.    PROVERB = 31,        /* Go Proverb         <=== last value */
  3772.    REFRESH = 17,        /* Refresh of a board     */
  3773.    SAVED = 18,            /* Stored command     */
  3774.    SAY = 19,            /* Say string         */
  3775.    SCORE = 20,            /* Score report         */
  3776.    SHOUT = 21,            /* Shout string         */
  3777.    SHOW = 29,            /* Shout string         */
  3778.    STATUS = 22,            /* Current Game status     */
  3779.    STORED = 23,            /* Stored games         */
  3780.    TELL = 24,            /* Tell string         */
  3781.    THIST = 25,            /* Thist report         */
  3782.    TIM = 26,            /* times command     */
  3783.    TRANSLATE = 30,        /* Translation info     */
  3784.    WHO = 27,            /* who command         */
  3785.    UNDO = 28,            /* Undo report         */
  3786. }  MessageType;
  3787.  
  3788.  
  3789. #define    S_BLACK  '0'
  3790. #define    S_WHITE  '1'
  3791. #define    S_EMPTY  '2'
  3792. #define    S_DAME   '3'
  3793. #define    S_WTERR  '4'
  3794. #define    S_BTERR  '5'
  3795. #define    S_HOSHI  '6'
  3796.  
  3797.  
  3798. typedef enum {
  3799.    LOGON = 0,
  3800.    PASSWORD = 1,
  3801.    PASSWD_NEW = 2,
  3802.    PASSWD_CONFIRM = 3,
  3803.    REGISTER = 4,
  3804.    WAITING = 5,
  3805.    PLAYING = 6,
  3806.    SCORING = 7,
  3807.    OBSERVING = 8,
  3808.    TEACHING = 9
  3809. }  State;
  3810. SHAR_EOF
  3811. fi
  3812. if test -f 'igc.h'
  3813. then
  3814.     echo shar: "will not over-write existing file 'igc.h'"
  3815. else
  3816. cat << \SHAR_EOF > 'igc.h'
  3817.  
  3818. #define MAXGAMES 50
  3819. #define MAXWHO 300
  3820. #define MAXNAME 11
  3821. #define MAXRANK 6
  3822. #define MAXFRIENDS 50
  3823. #define piece char
  3824.  
  3825. #ifdef BCOPY
  3826. #define bcopy(a,b,c) memcpy(b,a,c)
  3827. #endif
  3828.  
  3829. typedef struct {
  3830.    int id;
  3831.  
  3832.    int prompttype;        /* if return is prompt */
  3833.  
  3834.    int x, y;            /* used to report removed stones for scoring */
  3835.  
  3836.  
  3837.    struct {            /* if return is play */
  3838.       int x, y;
  3839.       int movenum;
  3840.       int color;
  3841.    }  moves[400];
  3842.  
  3843.    int movecount;
  3844.    int gamenum;
  3845.    int bcap, btime, bbyo;
  3846.    int wcap, wtime, wbyo;
  3847.  
  3848.    char text[10000];        /* text of message */
  3849.    int lines;            /* number of lines in text */
  3850.  
  3851.    int gamecount;        /* for data from the games command */
  3852.    struct gametype {
  3853.       int gnum;
  3854.       char white[MAXNAME], wrank[MAXRANK], black[MAXNAME], brank[MAXRANK];
  3855.       int mnum, bsize, hcap;
  3856.       float komi;
  3857.       int byo, obcount;
  3858.       char gametext[80];
  3859.    }  gamelist[MAXGAMES];
  3860.    char gamefirst[80];
  3861.  
  3862.  
  3863.    int boardsize, boardline;
  3864.    float wscore, bscore;
  3865.    piece board[19][19];
  3866.    int wnext;            /* white next?  Already have info for black. */
  3867.    char white[MAXNAME], wrank[MAXRANK], black[MAXNAME], brank[MAXRANK];
  3868.    int hcap;
  3869.  
  3870.    int beep;
  3871.  
  3872.    char kibitzer[40];
  3873.    char kibitz[300];
  3874.  
  3875.    int whocount;
  3876.    char *who[MAXWHO];
  3877.    char whodata[MAXWHO][40];
  3878.    char wholast[80];
  3879.    char whofirst[80];
  3880.  
  3881.    float mykomi;
  3882.  
  3883. }  message;
  3884.  
  3885.  
  3886.  
  3887. #define ONSERVER -1
  3888. #define MATCH -2
  3889. #define QUITMESG -3
  3890. #define REMOVE -4
  3891. #define SCOREUNDO -5
  3892. #define TIMEREP -6
  3893. #define TOOMANY -7
  3894. #define CHKOMI -8
  3895. #define STARTSCORE -9
  3896. #define INTRO -10
  3897. #define ENDGAME -11
  3898. #define ENDGAMEINFO -12
  3899.  
  3900. #define BLACK 1
  3901. #define WHITE 2
  3902. #define EMPTY 0
  3903. #define DAME 3
  3904. #define BTERR 4
  3905. #define WTERR 5
  3906.  
  3907. #define KEY -33
  3908. SHAR_EOF
  3909. fi
  3910. if test -f 'Makefile'
  3911. then
  3912.     echo shar: "will not over-write existing file 'Makefile'"
  3913. else
  3914. cat << \SHAR_EOF > 'Makefile'
  3915. CC = cc 
  3916.  
  3917. # if you get strstr undefined, add -DSTRSTR to the DEFINES line below
  3918. # if you get bcopy undefined, add -DBCOPY 
  3919. # if you get strtol undefined, add -DSTRTOL
  3920.  
  3921. # if you change something in the Makefile, you may need to 
  3922. # type rm *.o before trying to recompile.
  3923.  
  3924. # The -DDEBUG below causes igc to create dump?.igc files which 
  3925. # contain logs of each IGS session.  Remove the -DDEBUG
  3926. # to suppress creation of the dump files.  I may request 
  3927. # the log files from you if you report bugs.
  3928.  
  3929. DEFINES = -DDEBUG 
  3930.  
  3931. # You may want to change -g (include debug information) into
  3932. # -O for optimize.  If you do this, also run strip on the 
  3933. # igc file:  'strip igc'.  This will make the executable
  3934. # even smaller.
  3935.  
  3936. CFLAGS = -g  $(DEFINES) 
  3937.  
  3938. LIBS =     -lcurses -ltermlib
  3939.  
  3940. # link line for PTX.  System V systems need something like this:
  3941. #LIBS = -lcurses -ltermlib -lsocket -linet -lnsl 
  3942.  
  3943. # Under Irix running Yellow Pages, add -lsun to the link line
  3944.  
  3945. # Under RS/6000 AIX 3.1, remove the -ltermlib 
  3946.  
  3947. PROGRAM = igc
  3948.  
  3949. MAN = igc.doc
  3950.  
  3951. OBJ = socket.o igc.o parse.o ascii.o board.o
  3952.  
  3953. SRC = socket.c igc.c parse.c ascii.c board.c
  3954.  
  3955. HDRS =    numbers.h igc.h
  3956.  
  3957. FILES = README $(SRC) $(HDRS) Makefile igc.6 BUGS
  3958.  
  3959. all: $(PROGRAM) $(MAN)
  3960.  
  3961. $(PROGRAM): $(OBJ)
  3962.     @echo Loading...
  3963.     @$(CC) $(OBJ) $(LIBS) -o $(PROGRAM)
  3964.  
  3965. $(MAN): igc.6
  3966.     nroff -man igc.6 > $(MAN)
  3967.  
  3968. $(OBJ): $(HDRS)
  3969.  
  3970. shar: 
  3971.     @shar $(FILES) > $(PROGRAM).shar
  3972.  
  3973. shar2: 
  3974.     @shar -m 200000 -f $(PROGRAM) $(FILES) 
  3975.  
  3976. lint:
  3977.     lint $(SRC) -lcurses > lintout
  3978.  
  3979.  
  3980.  
  3981.  
  3982.  
  3983.  
  3984.  
  3985.  
  3986. SHAR_EOF
  3987. fi
  3988. if test -f 'igc.6'
  3989. then
  3990.     echo shar: "will not over-write existing file 'igc.6'"
  3991. else
  3992. cat << \SHAR_EOF > 'igc.6'
  3993. .TH IGC 6   "7 June 1993"
  3994. .SH NAME
  3995. igc - ascii client to Internet Go Server
  3996. .SH SYNOPSIS
  3997. .B igc
  3998. [\-s] [host [port]]
  3999. .SH DESCRIPTION
  4000. Go is an ancient asian strategy game based on the capture of
  4001. territory.
  4002. Players alternate, placing stones on the board and trying to surround
  4003. as many empty intersections as possible.  The 
  4004. .B Internet Go Server
  4005. allows players to meet and play interactive games.  
  4006. .B Igc
  4007. provides a more convenient interface for connections to the 
  4008. .B Internet Go Server.
  4009. .SH COMMAND LINE OPTIONS
  4010. .TP 8
  4011. .B \-s
  4012. Supresses autologin.
  4013. .LP
  4014. .TP 8
  4015. .B [host [port]]
  4016. Connects to specified host and port number.  The host can be specified
  4017. as a fully qualified hostname, or as an abbreviation.  If the
  4018. abbreviation is used, then the port number cannot be included.  
  4019. The shorthand names supported by default are:
  4020. .in +2m
  4021. .ta
  4022. .ta 7m +\w'mmmmmmm\ \ 'u +\w'hellspark.wharton.upenn.edu\ \ 'u +
  4023. .nf
  4024.  
  4025.     name    host address    port
  4026. site 0    icsi    hellspark.wharton.upenn.edu    6969
  4027. site 1    pasteur    ftp.pasteur.fr    6969
  4028.  
  4029. .fi
  4030. .in -2m
  4031. If no host is specified, then site 0 is used.  To connect to the French
  4032. site, for example, 
  4033. use 'igc pasteur'.  
  4034. (See the customization section for more information.)
  4035. .SH OPERATION
  4036. When 
  4037. .B igc 
  4038. is run, it opens a connection to the go server.  Unlike a straight
  4039. telnet connection, 
  4040. .B igc
  4041. does not print the '#>' prompt, and your normal suspend key (usually
  4042. ^Z) will suspend the client.  If you use telnet after using 
  4043. .B igc
  4044. the prompts from the server will be different because the server is in
  4045. client mode.  Log in with username and password at the numeric
  4046. prompts and then type 'toggle client' to get the normal prompts.
  4047. .LP
  4048. Initially, 
  4049. .B igc
  4050. acts as a direct connection to the server.  When a game is displayed,
  4051. the screen will be split into two windows:  one for the board on the
  4052. left, and one
  4053. for text interaction with the server on the right.  The 
  4054. ESC key will switch between
  4055. the two windows, and the ^L key will redraw the display (from either
  4056. window).  
  4057. .LP
  4058. When the server sends long messages such as the output from 
  4059. the 'games' command, the 'who' command, or the 'help' commmand, it
  4060. prints the message on top of the board.  Press any key to restore the
  4061. board.  If the message is longer than 22 lines, then the message will
  4062. be displayed in chunks.  
  4063. .LP
  4064. The names of the players appear above the board, followed by their
  4065. ranks, and the time remaining.  An arrow indicates whose turn
  4066. it is.  You can view only one game
  4067. at a time (either by observing, or by playing).  The number of 
  4068. that game is displayed to the left of the Black's name.
  4069. This number should be '--' if
  4070. you are not playing or observing a game.  To the right of Black's
  4071. name, above the right corner of the board (in 19x19 games),
  4072. is the number of handicap
  4073. stones.  This region is blank if the game is even. 
  4074. To the right of white's name is the komi for the game.  
  4075. Below the board, a line shows the number and coordinates of the last
  4076. move, and the captured stones are displayed.  The display shows the
  4077. number of black stones which were captured, followed by the
  4078. number of white stones captured.  
  4079. .LP
  4080. All of the commands which are active from the board window are single
  4081. keystroke commands.  The cursor can be moved around the board using
  4082. either the number keys (12346789), the emacs keys (^P ^N ^B ^F) or the
  4083. rogue keys (hjklyubn).  The board keeps track of all moves received so
  4084. that you can view the history of the game.  Note that the 
  4085. server's 'look' and 'status' commands do not generate a move history. 
  4086. When these commands are used, or when a game is scored, a snapshot of
  4087. the board is obtained from the server and temporarily placed on top of
  4088. the board.  The receipt of a move, or any attempt to move through the
  4089. game record, will restore the previous display.  When the status
  4090. display is active, the game number area in the upper right corner of
  4091. the screen reads "sta".  The previous display can be restored by the
  4092. client command 'restore'.
  4093. .LP
  4094. .TP 8
  4095. 0, space, return
  4096. Makes a move on the board.  (Send the coordinates of the cursor to the
  4097. server.)
  4098. .LP
  4099. .TP 8
  4100. c
  4101. Clears the marks on the board which indicate which piece was played
  4102. last.  
  4103. .LP
  4104. .TP 8
  4105. ^
  4106. Clears the server window to the right of the board.
  4107. .LP
  4108. .TP 8
  4109. comma, period (, and .)
  4110. Move backwards (comma) or forwards (period) through the moves in the
  4111. game currently displayed on the board.  If a new move arrives while you
  4112. are observing the game like this, you will be bounced back to the end
  4113. of the game.  
  4114. .LP
  4115. .TP 8
  4116. <, >
  4117. Move backwards or forwards by sets of ten moves
  4118. through the game currently displayed on the board.  
  4119. .LP
  4120. .TP 8
  4121. s, e
  4122. Jump to start (s) or end (e) of the game displayed on the board.
  4123. .LP
  4124. .TP 8
  4125. f, /
  4126. Find the time in the game when a stone was played at the current
  4127. cursor location, and jump to that move.  If a stone was played on one
  4128. point several times, this command jumps to the latest. 
  4129. .LP
  4130. Commands in the server window are words rather than single characters.
  4131. These commands will work in the full screen mode as well when appropriate.
  4132. The backspace and delete keys will remove the last character you
  4133. typed, and ^U will kill the whole line.  
  4134. .LP
  4135. .TP 4
  4136. helpigc 
  4137. Display a brief help screen.
  4138. .LP
  4139. .TP 4
  4140. observe <n>
  4141. Begin observing game n.  If you are already observing a game, this
  4142. command will stop observing that game and begin observing game n.
  4143. If you are observing game n, then this command will stop observing
  4144. game n.  This command can be abbreviated as 'ob'. 
  4145. .LP
  4146. .TP 4
  4147. unobserve
  4148. Stop observing the game you are watching.  This command can be
  4149. abbreviated as 'unob'.  
  4150. .LP
  4151. .TP 4
  4152. peek <n>
  4153. Peeks at game n.  Fetches all the moves from that game without
  4154. observing so that you can play the game back from the start, or just
  4155. see what it looks like.
  4156. .LP
  4157. .TP 4
  4158. restore
  4159. Restores the active game display which was on the board before
  4160. a 'look' or 'status' command.  This command is only valid when the
  4161. upper left corner of the screen says "sta". 
  4162. .LP
  4163. .TP 4
  4164. goto <n>
  4165. Goes to move n in the game displayed on the board.
  4166. .LP
  4167. .TP 4
  4168. clear
  4169. Clears the server window
  4170. .LP
  4171. .TP 4
  4172. noboard
  4173. Removes the board and returns to full screen interaction with the
  4174. server.
  4175. .LP
  4176. .TP 4
  4177. user <name>
  4178. Prints the line for <name> from the output of the last who command.
  4179. .LP
  4180. .TP 4
  4181. sort <sort-type>
  4182. Sets the sorting method for output from the server's 'who' command. 
  4183. Available sorting methods are: none, rank, rating, name, and game.  The 'none'
  4184. type does no sorting.  The 'name' type sorts by name, 'rank' sorts by
  4185. rank, 'rating' sorts by ranks, but distinguishes between stated ranks
  4186. and computed ones, 'idle' sorts by idle time and 'game' sorts first by 
  4187. the game a player is playing in,
  4188. second by whether a player is open for games, and finally by rank.  
  4189. The default sorting method is 'name'. 
  4190. .LP
  4191. .TP 4
  4192. gamessort <games-sort-type>
  4193. Sets the sorting method for output from the server's 'games' command.
  4194. Available sorting methods are: none, number, obcount.  The 'number' type
  4195. sorts by game number and is the default.  The 'obcount' type sorts
  4196. by the number of observers watching each game.  
  4197. .LP
  4198. .TP 4
  4199. filter 
  4200. Enable filtering of shout commands for friends.  (See 'friend' command.)
  4201. .LP
  4202. .TP 4
  4203. nofilter
  4204. Disable filtering of shout commands for friends.  (See 'friend' command.)
  4205. .LP
  4206. .TP 4
  4207. friend [name]
  4208. If the name is given, add that name to the list of friends.  If no
  4209. name is given, then print the current list of friends.  When filtering
  4210. is enabled, only shout commands which start with a name on the friends
  4211. list will be printed.  The friends list is limited to 50 names.
  4212. .LP
  4213. .TP 4
  4214. unfriend name
  4215. Remove the specified name from the friends list.
  4216. .LP
  4217. .TP 4
  4218. inverse
  4219. Switch board display to inverse video.  (This is the default display).
  4220. .LP
  4221. .TP 4
  4222. noinverse
  4223. Switch board display to regular video.
  4224. .LP
  4225. .TP 4
  4226. invedge
  4227. Display edges with inverse video.
  4228. .LP
  4229. .TP 4
  4230. noinvedge
  4231. Display edges with normal video. (This is the default).
  4232. .LP
  4233. .TP 4
  4234. chars <list>
  4235. Sets the board characters.  The order is
  4236. empty, black, white, dame, black territory, white territory, hoshi
  4237. point, border.  The characters should appear without spaces betwee
  4238. them.  The default character set is .#O?+-+ with a space for the
  4239. border character.
  4240. .LP
  4241. .TP 4
  4242. border <char>
  4243. Sets the border character to char.  If char is omitted then the border
  4244. is turned off.  (This is the default.)
  4245. .LP
  4246. .TP 4
  4247. beeps <n>
  4248. Sets the number of beeps sent when sending a beep.  The
  4249. default is one.
  4250. .LP
  4251. .TP 4
  4252. saybeep
  4253. Causes 
  4254. .B igc
  4255. to beep when your opponent says something to you during a game using
  4256. the say command.  Does not cause
  4257. messages sent with the tell command to beep.
  4258. .LP
  4259. .TP 4
  4260. nosaybeep
  4261. Do not beep when your opponent says something to you with the say
  4262. command.  (This is the default.)
  4263. .LP
  4264. .TP 4
  4265. tellbeep
  4266. Causes
  4267. .B igc
  4268. to beep if anyone tells you anything at any time.  
  4269. Does not cause messages sent with the say command to beep.
  4270. .LP
  4271. .TP 4
  4272. notellbeep
  4273. Do not beep when people tell things to you.  (This is the default.)
  4274. .LP
  4275. .TP 4
  4276. prefix <text>
  4277. Adds text to every line you type to the server.  All characters before
  4278. your text will be used in the prefix.  The purpose of this command is
  4279. to make it easier to hold conversations with someone. 
  4280. To talk with goplayer, you might type 'prefix tell goplayer ' (note
  4281. the extra space).  All subsequent lines would be sent to goplayer.
  4282. If you start a line with '!' then the prefix will not be used. 
  4283. To turn off the prefix, type '!prefix'. 
  4284. When the prefix is active and the board is displayed, the prefix text
  4285. is displayed at the bottom of the server window.
  4286. .LP
  4287. .TP 4
  4288. edgemarks
  4289. Turns on display of marks at the edge of the board to indicate last
  4290. move.
  4291. .LP
  4292. .TP 4
  4293. noedgemarks
  4294. Turns off display of marks at the edge of the board to indicate last
  4295. move. (This is the default.)
  4296. .LP
  4297. .TP 4
  4298. piecemarks
  4299. Turns on display of marks around the last stone played.  (This is
  4300. the default.)
  4301. .LP
  4302. .TP 4
  4303. nopiecemarks
  4304. Turns off display of marks around the last stone played.
  4305. .SH CUSTOMIZATION
  4306. The file 
  4307. .B .igcrc
  4308. is used to do initialization.  You do not need to have this file, but
  4309. it can set up 
  4310. .B igc
  4311. to suit your desires and it can automatically log you in.
  4312. You create this file in your home directory yourself, using 
  4313. a text editor (emacs, vi).  
  4314. The following server window commands are supported in the 
  4315. .B .igcrc
  4316. file: inverse, noinverse, invedge, noinvedge, beeps, saybeep, 
  4317. nosaybeep, chars, border, sort, gamessort, friend, unfriend, filter, 
  4318. nofilter.  
  4319. They can be used to configure the display as desired.
  4320. .LP
  4321. Some special commands are supported as well:
  4322. .LP
  4323. .TP 4
  4324. nointro
  4325. Supresses the display of the login message which is printed before
  4326. you login. 
  4327. .LP
  4328. .TP 4
  4329. login <name>
  4330. Causes 
  4331. .B igc
  4332. to automatically send <name> as your login name when the connection is
  4333. established.  (This is suppressed by the \-s option.)
  4334. .LP
  4335. .TP 4
  4336. password <password>
  4337. Causes 
  4338. .B igc
  4339. to send <password> as your password.  If you use this command, you
  4340. should make sure that your 
  4341. .B .igcrc
  4342. file is not world readable.  Use the command 'chmod 600 .igcrc' to 
  4343. set the insure that this file is not world readable.
  4344. (Transmission of <password> is supressed by the \-s option.)
  4345. .LP
  4346. .TP 4
  4347. site <number> <name> <address> <port>
  4348. The program keeps a table of ten sites labeled site 0 through site 9.
  4349. By specifying the desired <number>, you can define new servers.
  4350. A server has <name> as its shorthand
  4351. reference, <address> as a fully qualified internet address, and port
  4352. number <port>.  By changing site 0, you can change the default site
  4353. which is used if
  4354. .B igc
  4355. is invoked without parameters.  By default, the first two sites are
  4356. set as described under command line options.  The remaining eight
  4357. sites are undefined.  
  4358. .SH BUGS
  4359. .LP
  4360. The server allows command abbreviation, but the client does not. 
  4361. .LP
  4362. The server doesn't correctly mark the ends of games, so if a game
  4363. ends while you are playing/observing, the client may still think
  4364. you are playing/observing.  The number in the upper left will
  4365. say '--' if the client realizes you are not doing anything.  If
  4366. it doesn't, press return a few times in the server window.
  4367. .LP
  4368. If someone who is playing a game changes their rank, the change
  4369. will not be reflected on the screens of other people watching or
  4370. playing that game.  
  4371. .LP
  4372. If komi changes during a game, the observers will not see the change.
  4373. (The players will.)
  4374. .LP
  4375. The program cannot handle boards larger than 19x19.
  4376. .SH AUTHOR
  4377. Adrian Mariano (adrian@u.washington.edu, adrian on IGS)
  4378. .SH SEE ALSO
  4379. LaTeX and Postscript documentation for the IGS is available on
  4380. ftp.u.washington.edu in public/go/prog/igs.tex.Z and public/go/prog/igs.ps.Z.  
  4381. .LP
  4382. Other programs: mgt, pcigc, stigc, xigc, xgospel
  4383.  
  4384. SHAR_EOF
  4385. fi
  4386. if test -f 'BUGS'
  4387. then
  4388.     echo shar: "will not over-write existing file 'BUGS'"
  4389. else
  4390. cat << \SHAR_EOF > 'BUGS'
  4391. can't load selfgames
  4392. doesn't intercept partial commands
  4393. SHAR_EOF
  4394. fi
  4395. exit 0
  4396. #    End of shell archive
  4397.